带接口的架构/设计(重构帮助)

Rom*_*iri 3 c# architecture rss solid-principles

我需要你帮我做一个我不满意的设计.该应用程序正在消费RSS新闻(文章的RSS,以及每篇文章的评论RSS).

我创建了一个名为IDataService的接口,它提供了数据提供程序的基本行为.

public interface IDataService
{
    Task<List<Item>> GetItemsAsync(string url, IItemsParser parser);
    Task<List<Comment>> GetItemCommentsAsync(string url, ICommentsParser parser);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,每个函数都将web服务url(在我的情况下为RSS feed url)和一些知道如何处理数据的解析器的接口作为参数.

这些是两个解析的接口:

public interface IItemsParser
{
    List<Item> ParseRawData(string rawData);
}

public interface ICommentsParser
{
    List<Comment> ParseRawData(string rawData);
}
Run Code Online (Sandbox Code Playgroud)

现在让我们具体一点,这是实现类:

public class MyRSSDataService : IDataService
{
    public async Task<List<Item>> GetItemsAsync(string url, IItemsParser parser)
    {
        using (var httpClient = new HttpClient())
        {
            var response = await httpClient.GetAsync(new Uri(url));

            if (response.IsSuccessStatusCode)
            {
                var jsonResponse = await response.Content.ReadAsStringAsync();
                List<Item> items = parser.ParseRawData(jsonResponse);

                return items;
            }
            else
            {
                throw new NetworkConnectionException(response.StatusCode.ToString());
            }
        }
    }


    public async Task<List<Comment>> GetItemCommentsAsync(string url, ICommentsParser parser)
    {
        using (var httpClient = new HttpClient())
        {
            var response = await httpClient.GetAsync(new Uri(url));

            if (response.IsSuccessStatusCode)
            {
                var jsonResponse = await response.Content.ReadAsStringAsync();
                List<Comment> comments = parser.ParseRawData(jsonResponse);

                return comments;
            }
            else
            {
                throw new NetworkConnectionException(response.StatusCode.ToString());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我觉得我真的违反了DRY原则,而且我对我制作的看起来如此相似的界面感觉不太好.

Joh*_*ner 6

使用泛型:

public interface IDataService
{
    Task<List<T>> GetDataAsync<T>(string url, IParser<T> parser);
}

public interface IParser<T>
{
    List<T> ParseRawData(string rawData);
}
Run Code Online (Sandbox Code Playgroud)

然后你的实现看起来像这样:

public class DataService : IDataService
{
    public async Task<List<T>> GetDataAsync<T>(string url, IParser<T> parser)
    {
        // Do work
        return parser.ParseRawData("blah");
    }
}

public class ItemParser : IParser<Item>
{
    public List<Item> ParseRawData(string rawData)
    {
        // Do work
    }
}

public class CommentParser : IParser<Comment>
{
    public List<Comment> ParseRawData(string rawData)
    {
        // Do work
    }
}
Run Code Online (Sandbox Code Playgroud)

现在当你使用它时,它很简单:

var x = new DataService();
var y = new ItemParser();

await x.GetDataAsync("", y);

var z = new CommentParser();
await x.GetDataAsync("", z);
Run Code Online (Sandbox Code Playgroud)