IoC服务的抽象类或接口?

时间:2011-03-25 14:46:20

标签: design-patterns .net-3.5 inversion-of-control

我目前正在使用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。

2 个答案:

答案 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之外的其他任何东西都是个坏主意。