此article说明了如何使用所有基本的CRUD操作创建通用的HttpClient类。然后,它为特定的POCO对象(称为成员)创建类型特定的存储库。
我无法理解的是,对于MemberReposity类的需求是否恰好返回了GenericHttpClient类针对特定类型返回的内容?我不能简单地将GenericHttpClient重命名为GenericReposity,然后将其用于所有POCO对象CRUD操作吗?换句话说,如果每个对象都只需要基本的CRUD操作,为什么还要为每个对象需要一个唯一的存储库?
我可以像这样在我的表单上实例化它们:
private GenericReposity<Customer, int> _customerClient = new GenericReposity<Customer, string>(url, "api/Customers/");
然后以这种方式获得客户:
_customerClient.GetAsync(5);
我在这里遗漏了一点吗?
更新
在阅读了有关反模式的信息后,我设计了一个基本的存储库界面,如下所示:
internal interface IGenericRepository<T, in TResourceIdentifier>
{
Task<IEnumerable<T>> GetManyAsync();
Task<T> GetAsync(TResourceIdentifier id);
Task PutAsync(T model);
Task<T> PostAsync(T model);
Task DeleteAsync(TResourceIdentifier id);
}
然后我实现了它:
public class GenericRepository<T, TResourceIdentifier> : IDisposable, IGenericRepository<T, TResourceIdentifier>
where T : class
{
private bool _disposed;
protected HttpClientHelper<T, TResourceIdentifier> Client;
protected GenericRepository(string addressSuffix)
{
Client = new HttpClientHelper<T, TResourceIdentifier>(Properties.Settings.Url, addressSuffix);
}
public async Task<IEnumerable<T>> GetManyAsync()
{
return await Client.GetManyAsync();
}
// All other CRUD methods and dispose
}
然后,我为每个实体创建了自定义存储库界面。例如:
internal interface IOrderRepository : IGenericRepository<Order, int>
{
Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition );
}
最后,我实现了自定义存储库:
public class OrderRepository : GenericRepository<Order, int>, IOrderRepository
{
public OrderRepository(string addressSuffix) : base(addressSuffix)
{
}
public async Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition)
{
//get all the orders (GetManyAsync()) and then returns the ones meeting the condition
}
}
这样,我可以获得所有简单的CRUD操作,而不必为每个实体以及任何自定义对象一一实现。 这是正确的方法吗?还是这被认为是反模式?
答案 0 :(得分:1)
总有一天,您可能希望添加每种实体类型唯一的内容,例如数据验证,或者在数据静止时加密个人信息。
答案 1 :(得分:1)
您的新方法(更新后)看起来很棒。
由此,您可以绕过通用存储库的所有缺点;仍然利用基础通用存储库中的代码重用。
没什么大不了,但是可以考虑在基础存储库protected
中使用所有方法,以便只能在具体存储库中访问这些方法。当然,如果所有具体存储库都采用该方法,则可以忽略该建议。