我目前正在使用IoC在项目中提供存储库的具体实现。我读过的所有示例都使用接口作为服务的定义。但是,阅读Microsoft的建议后,建议prefer abstract classes over interfaces。
我发现这与模板模式相结合可以减少重复。例如,给一个带有属性Product
的{{1}}类我可以使用存储库的接口,例如:
IsActive
如果常见任务是加载活动产品,那么我需要这样做:
interface IProductRepository
{
IEnumerable<Product> Load();
}
其中IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive);
是具体实现。如果我使用了一个抽象类,如:
repository
然后我可以使用
加载活动产品abstract class ProductRepository
{
protected abstract IEnumerable<Product> LoadCore();
public IEnumerable<Product> Load()
{
return LoadCore().Where(x => x.IsActive);
}
}
加载产品信息的所有实现都在派生IEnumerable<Product> activeProducts = repository.Load();
的contrete类中,因此没有与persistance层的耦合。如果发现存在另一个通常执行的活动,则可以将其添加到基类中,作为无法使用接口无法完成的非破坏性更改。
使用接口而不是抽象类有什么好处?我可以遇到使用抽象类的哪些潜在缺点?
我使用Castle Windsor作为IoC控制器和.Net framework 3.5。
答案 0 :(得分:7)
我不认为这个问题取决于IoC;大多数这些框架并不关心您使用哪种框架。
在抽象基类上使用接口之间的一个大问题是interfaces cannot be versioned well。
因此,抽象基类通常是更好的选择。我不认为使用抽象基类有任何缺点,除了获得支持问题,例如“为什么我不能创建这种类型的实例?”
答案 1 :(得分:2)
该推荐来自Framework Design Guidelines。 Microsoft的此建议专门针对可重用的类库。换句话说:.NET框架本身就是框架。如果您要创建业务线应用程序,则此准则不适用。它不适用,因为您不太可能在业务线应用程序中出现版本控制问题,因为您可以控制与类/接口对话的所有客户端代码。对于可重用的库,情况当然不是这样。
偶数the article of Phil Haack,Will引用描述了这一点:
同样,这些指南是具体的 框架开发(for 静态类型语言),而不是 到其他类型的软件 发展。
因此,删除版本控制问题可能不是使用基类的好参数。但是保持代码DRY可能是。但是,使用基类和接口并不是互斥的;您可以让abstract class ProductRepository
实施IProductRepository
。但是,如果你这样做,那么除了IProductRepository
之外的其他任何东西都是个坏主意。