【问题标题】:c# polymorphism + generics design - advice neededc# 多态性 + 泛型设计 - 需要建议
【发布时间】:2017-06-23 07:01:21
【问题描述】:

我有一个TrendProviders 的层次结构,用于提供来自不同来源的一系列数据点(趋势)。

我已经开始使用通用接口:

public interface ITrendProvider<T> where T: TrendResult
{
    IEnumerable<T> GetTrends(); 
}

TrendResult是一个带有获取到的趋势数据和运行状态码的结​​果类:

public class TrendResult
{
    public TrendResult()
    {
        Points = new Dictionary<DateTimeOffset, decimal>();
    }

    public TrendResultCode Code { get; set; }
    public string Name { get; set; }
    public string Identifier { get; set; }
    public Dictionary<DateTimeOffset, decimal> Points { get; set; }
}

TrendResultCode如下:

public enum TrendResultCode
{
    OK,
    DataParseError,
    NoData,
    UnknownError
}

还有两种(到目前为止)更详细的接口:

  • IFileTrendProvider - 用于从任何文件中获取趋势。

  • IServerTrendProvider - 用于从远程服务器获取趋势,例如使用 FTP。

IFileTrendProvider 是这样的:

public interface IFileTrendProvider : ITrendProvider<TrendResult>
{
    IFileReader FileReader {get; set}
    FileTrendDiscoveryPattern Pattern {get; set;}  
}

IServerTrendProvider 是这样的:

public interface IServerTrendProvider : ITrendProvider<TrendResult>
{
    IClient Client { get; set; }
    Dictionary<string, string[]> RequestedServerTrendIDs { get; set; }
}

实现接口的具体类如下:

FileTrend 类型之一:

public class GenericFileTrendProvider : IFileTrendProvider<TrendResult>
{
    public GenericFileTrendProvider() { }

    public IFileReader FileReader {get; set}
    public FileTrendDiscoveryPattern Pattern {get; set;}  

    public IEnumerable<TrendResult> GetTrends()
    {
       // Some code to obtain trends from file using FileReader
    }
}

还有ServerTrend 类型之一:

public class ServerATrendProvider : IServerTrendProvider<TrendResult>
{
    public ServerATrendProvider () { }

    public IClient Client { get; set; }
    public Dictionary<string, string[]> RequestedServerTrendIDs { get; set;}

    public IEnumerable<TrendResult> GetTrends()
    {
       // Some code to obtain trends from remote server using Client
    }
}

现在,我想实现什么以及在哪里需要您的帮助和建议:

IFileReader 引入了自己的错误代码:

public enum FileReadResultCode
{
    OK,
    FileAlreadyOpen,
    FileNotFound,
    UnknownError
}

IClient还介绍了它的具体操作错误码:

public enum ClientCode
{
    OK,
    InvalidCredentials,
    ResourceNotFounds,
    UnknownError
}

由于IFileReaderIClient都返回了自己的错误码,我怎么能在GetTrends()方法返回的TrendResult对象中插入它们,这样最后也会有一些关于“内部”错误,不仅仅是TrendResult具体错误?

我需要一些灵活的解决方案 - 我正在考虑从 TrendResult 继承并为每个具体提供者创建一个 FileTrendResultServerTrendResult,并为两者定义一个特定的错误枚举,以便它们返回自己的结果类型,但可以通过其他方式完成吗?

【问题讨论】:

  • 好问题pitersmx。通常我们不会在帖子中添加任何问候或感谢,以确保帖子中的噪音尽可能小。我已经为你编辑了你的感谢,你知道的。
  • 现在我需要一些很好的答案:)
  • 特定结果是否适用于单个TrendResult,或者对于从源(例如文件)读取的所有趋势结果是否相同。例如,GenericFileTrendProvider 是否一次读取多个文件,以便返回的一些 TrendResults 可能具有代码 FileNotFound,而其他可能具有 Ok 或其他代码?
  • @Markus 在GetTrends() 方法中,我使用yield 一次返回一个TrendResult,然后将其处理并存储在数据库中。因此,对于应该从文件或服务器读取的每一个趋势,都应该返回一个TrendResult,其中包含与该单一趋势相关的错误的确切详细信息 - 如果有任何错误,我必须推送它到记录器。
  • 继续:我只需要一些方便的方法来传递有关错误的确切信息 - 为什么无法检索趋势。当然,对于我假设从一个当前由其他人打开的文件中读取 10 个趋势的情况,我将使用 FileAlreadyOpen 代码获得 10x TrendResult - 这是想要的结果。

标签: c# generics polymorphism


【解决方案1】:

您可以更改 TrendResult 类以存储异常列表并获取摆脱枚举:

public class TrendResult
{
    // ...    
    // public TrendResultCode Code { get; set; }
    public IEnumerable<Exception> Errors { get; set; }
    // ...
}

这样,您可以存储错误的完整信息,包括堆栈跟踪和其他有价值的信息(如果单个TrendResult 中存在多个问题,则可以存储多个错误)。即使出现意外错误,您也可以存储详细信息,而不是出现难以追踪的未知错误。

如果TrendResult 在枚举中没有任何项目,则它没有问题。否则,您可以将信息写入日志。

实现遵循Open/Closed principle,因此如果有导致错误的新条件,您不必更改处理TrendResults 的实现。

对于您的业务例外情况,例如解析错误时,您应该创建特定的异常类型,以便以后能够根据它们的类型分析这些错误。

【讨论】:

  • 谢谢,我会试试的。我开始非常喜欢你的解决方案。我认为这对我来说是正确的方式。再次感谢!
【解决方案2】:

由于 IServerTrendProvider 将从其他计算机接收 TrendResults,因此在一般情况下您将无法使用 System.Exception

在这些情况下,人们会退回到字符串 - 无论操作系统如何,它们都始终受到支持。

public class TrendResult
{
   public string[] ErrorMessages;  // Error messages - could be the stack trace
   public int[]    ErrorCodes;     // Os-specific error numbers
}

在错误消息中发送源代码片段(例如名称、堆栈跟踪)时考虑安全性,因为这些可能对黑客有用。

【讨论】:

    猜你喜欢
    • 2011-11-13
    • 2013-11-26
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多