依赖注入和程序集引用

时间:2012-09-02 03:44:27

标签: c# asp.net-mvc dependency-injection

我希望有一个关于MVC应用程序中依赖注入的基本问题,我一直无法找到满意的答案。我的应用程序包含一个MVC 3项目,一个服务层类库(SL)和一个数据访问类库(DAL)。 SL和DAL都包含各自的接口和实现。 MVC项目引用了SL和DAL项目。 MVC项目将创建DAL的实现并将其注入到接受DAL接口的SL构造函数中。

我所担心的是为了让SL接受DAL接口作为参数,它还需要对DAL项目的引用(接口碰巧存在但也是实现),这似乎违反了DI,因为现在两者都是MVC和SL项目需要引用DAL程序集。

长话短说,将DAL接口移动到自己的项目中是否更有意义,这样SL只需要引用接口项目而不是实现项目? MVC项目显然需要引用接口和实现项目,DAL也需要引用接口项目。这似乎是一种更干净的做事方式,即使它为我的解决方案增加了另一个项目,这并没有给我带来太多麻烦。我也看到了在SL中存储DAL接口的建议,并且有DAL参考SL,但这对我来说似乎不对。任何见解或建议都表示赞赏。谢谢!

4 个答案:

答案 0 :(得分:5)

看看洋葱建筑:

http://jeffreypalermo.com/blog/the-onion-architecture-part-1/

http://jeffreypalermo.com/blog/the-onion-architecture-part-2/

http://jeffreypalermo.com/blog/the-onion-architecture-part-3/

让UI程序集引用所有服务和业务逻辑程序集是完全没错的。服务层显然应该引用不应该依赖于任何更高级别的基础结构程序集。

答案 1 :(得分:2)

真正的组件必须将它们的接口及其实现放在不同的程序集中。

这允许您像加载项一样动态加载适当的实现。通常它也是避免循环引用的唯一方法。作为示例,DAL需要知道模型(业务类),并且模型可能希望通过DAL调用延迟加载依赖模型,这会创建循环引用(.NET禁止循环程序集引用)。如果接口位于单独的程序集中,则DAL和Model程序集都引用了两个接口程序集,并通过构造函数注入依赖项。

// Assembly: Model contracts

public interface IModelA
{
    IModelB ModelB { get; }
    ...
}

public interface IModelB
{
    ...
}

public interface IModelFactory
{
    IModelA CreateModelA();
    IModelB CreateModelB();
}

// Assembly: DAL contracts, references Model contracts

public interface IDAL
{
    IModelA LoadA(int id);
    IModelB LoadB(int id);
}

// Assembly: Model implementation, references Model and DAL contracts

public class ModelA : IModelA
{
    private IDAL _dal;

    public ModelA (IDAL dal)
    {
        _dal = dal;
    }

    private IModelB _modelB;
    public IModelB ModelB
    {
        get {
            if (_modelB == null) {
                _modelB = _dal.LoadB(5);
            }
            return _modelB;
        }
    }
}

// Assembly: DAL implementation, references Model and DAL contracts

public class DAL : IDAL
{
    private IModelFactory _modelFactory;

    public DAL(IModelFactory _modelFactory)
    {
        _modelFactory = modelFactory;
    }

    public IModelA LoadA(int id)
    {
        IModelA modelA = _modelFactory.CreateModelA();
        // fill modelA with data from database
        return modelA;
    }

    public IModelB LoadB(int id)
    {
        IModelB modelB = _modelFactory.CreateModelB();
        // fill modelB with data from database
        return modelB;
    }
}

答案 2 :(得分:1)

正如规则所说,只要你依赖于接口而不是具体的实现就没关系。所以你可以做的是将你的接口放在不同的程序集中,并在任何你想要的地方引用它们。

答案 3 :(得分:1)

引用具有混凝土类型的程序集可能是个问题,但这取决于您要实现的目标。通过让服务仅依赖于抽象,您可以实现松散耦合的代码。这提高了可维护性。

让BL程序集仅引用包含抽象(而不是实现)的程序集,允许您独立部署部分软件。比如说您希望将软件部署到不同的客户,并且您有多种DA层,但不希望将所有DA风格部署到所有客户(例如,因为他们需要为每个DA层付费,或者可能你试图保护你的知识产权)。

因此,如果分离不是部署的关注点,则不必创建单独的程序集。