繁体   English   中英

依赖注入和程序集引用

[英]Dependency Injection and assembly references

我有一个我希望是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,但这对我来说似乎不对。 任何见解或建议都表示赞赏。 谢谢!

看看洋葱建筑:

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程序集引用所有服务和业务逻辑程序集是完全正确的。 服务层显然应该引用不应该依赖于任何更高级别的基础结构程序集。

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

这允许您像加载项一样动态加载适当的实现。 通常它也是避免循环引用的唯一方法。 作为示例,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;
    }
}

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM