3

我有一个我希望是关于 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 也需要引用接口项目。这似乎是一种更清洁的做事方式,即使它在我的解决方案中添加了另一个项目,这并没有让我很困扰。我还看到了将 DAL 接口存储在 SL 中并具有 DAL 参考 SL 的建议,但这对我来说似乎不正确。任何见解或建议表示赞赏。谢谢!

4

4 回答 4

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

于 2012-09-02T03:48:30.857 回答
2

真正的组件必须在单独的程序集中有它们的接口和它们的实现。

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

// 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;
    }
}
于 2012-09-02T15:21:17.520 回答
1

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

于 2012-09-02T04:04:05.910 回答
1

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

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

因此,如果分离不是部署的问题,您不必创建单独的程序集。

于 2012-09-02T14:42:59.200 回答