IoC服务的抽象类或接口?

det*_*lor 7 design-patterns inversion-of-control .net-3.5

我目前正在使用IoC在项目中提供存储库的具体实现.我读过的所有示例都使用接口作为服务的定义.但是,阅读Microsoft的建议后,建议您更喜欢接口上的抽象类.

我发现这与模板模式相结合有用,可以减少重复.例如,给一个Product具有属性的类IsActive我可以使用存储库的接口,例如:

interface IProductRepository
{
    IEnumerable<Product> Load();
}
Run Code Online (Sandbox Code Playgroud)

如果一个常见的任务是加载活动产品,那么我需要这样做:

IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive);
Run Code Online (Sandbox Code Playgroud)

repository具体实施在哪里.如果我使用了一个抽象类,例如:

abstract class ProductRepository
{
    protected abstract IEnumerable<Product> LoadCore();

    public IEnumerable<Product> Load()
    {
        return LoadCore().Where(x => x.IsActive);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以使用加载活动产品

IEnumerable<Product> activeProducts = repository.Load();
Run Code Online (Sandbox Code Playgroud)

加载产品信息的所有实现都在派生的contrete类中,ProductRepository因此不存在与持久层的耦合.如果发现存在另一个通常执行的活动,则可以将其添加到基类中,作为使用接口无法完成的非破坏性更改.

使用接口而不是抽象类有什么好处吗?我可以遇到使用抽象类的哪些潜在缺点?

我使用Castle Windsor作为IoC控制器和.Net framework 3.5.

小智 7

我不认为这个问题取决于IoC; 大多数这些框架并不关心您使用哪种框架.

在抽象基类上使用接口之间的一个大问题是接口无法很好地进行版本控制.

因此,抽象基类通常是更好的选择.我不认为使用抽象基类有任何缺点,除了获得诸如"为什么我不能创建这种类型的实例?"之类的支持问题.

  • 好吧,一般来说,我们知道我们应该"赞成组合而不是继承",所以使用基类违背了这个建议.在更具体的层面上,角色接口倾向于提供比头接口更好的抽象.但是,角色接口的真正好处是类可以实现多个接口.继承是不可能的,因此使用基类会使我们朝向Header接口的方向,从而导致糟糕的抽象. (4认同)
  • 基类的另一个问题是它们可以对构造函数设置限制.这种限制通常是漏洞抽象,因此最好避免.另一件事:如果基类使用受保护的虚拟成员,则无法围绕这些方法创建适当的装饰器. (2认同)
  • 当然:抽象基类也提供了一些好处 - 主要是你提到的版本支持.所以在某些情况下我会选择公开ABC而不是界面,但你必须知道何时做什么. (2认同)