c# полиморфизм + дженерики дизайн-советы, необходимые

у меня есть иерархия 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
}

как: IFileReader и IClient также возвращает свои собственные коды ошибок, как я мог бы ввести их в

2 ответов


вместо того, чтобы иметь заранее определенный список возможных ошибок в нумерации (TrendResultCode, FileReadResultCode, ClientCode, ...) вы можете изменить TrendResult класс для хранения списка исключений и избавиться от перечислений:

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

таким образом, вы можете сохранить полную информацию об ошибке, включая трассировку стека и другую ценную информацию (или несколько ошибок, если в одном TrendResult). Даже для непредвиденных ошибок, вы можете хранить детали вместо того, чтобы иметь неизвестную ошибку, которую трудно отследить.

если TrendResult не имеет никаких элементов в перечислении, нет никаких проблем с ним. В противном случае, вы можете поместить информацию в журнал.

реализация следует за открытый/закрытый принцип, поэтому вам не нужно изменять реализацию, которая обрабатывает TrendResults если возникают новые условия, которые приводят к ошибке.

для ваших бизнес-исключений, например при анализе ошибок необходимо создать определенные типы исключений, чтобы впоследствии анализировать эти ошибки на основе их типа.


поскольку IServerTrendProvider будет получать TrendResults с других компьютеров, вы не сможете использовать