IOC / DI - 为什么我必须引用所有层/组件的应用程序的入口点?(Ioc/DI - Why

2019-10-30 12:34发布

(与此相关的问题, EF4:为什么代理创建具有当启用延迟加载启用? )。

我是新来的DI,所以大家多多包涵。 据我所知,容器负责实例化我所有的注册的类型的,但为了做到这一点,需要在我的解决方案及其引用的所有的DLL的参考。

如果我不使用DI容器,我就不必引用的EntityFramework库在我MVC3应用程序,只有我的业务层,这将引用我的DAL /回购层。

我知道,在一天结束的所有DLL都包含在bin文件夹,但我的问题是必须通过以能够发布一个WAP与所有必要的文件在VS“添加引用”明确引用它。

Answer 1:

如果我不使用DI容器,我就不必引用的EntityFramework库在我MVC3应用程序,只有将引用我的DAL /回购层我的业务层。

是的,这正是DI如此努力避免的情况:)

随着紧密耦合的代码,每个库可能只有几个引用,但这些再有其他的引用,创建依赖的深层图,如下所示:

因为依赖图是深的,这意味着大多数库沿着很多其他依赖的拖动-例如,在图中, 库C 沿H,图书馆E,图书馆Ĵ,图书馆男,图书馆K图书馆Ñ拖动。 这使得更难独立于其余重复使用的每个库-例如在单元测试 。

然而,在松散耦合应用,由所有引用移动到组合物根 , 依赖图被严重压扁

正如绿色所示,它现在可以重用库C没有沿任何不需要依赖拖动。

然而,所有的说,很多DI容器,你不必硬引用添加到所有需要的库。 相反,可以使用后期无论是在基于常规组装扫描(优选的)或XML配置的形式结合

当你这样做,但是,你必须记住的组件复制到应用程序的bin文件夹,因为不再自动发生。 就个人而言,我很少发现值得额外的努力。

这个答案的更详细的版本中可以找到此摘录从我的书依赖注入,原则,实践模式 。



Answer 2:

如果我不使用DI容器,我就不必引用的EntityFramework库在我MVC3应用

使用DI容器即使,你没有让你的MVC3项目引用EF,但你(隐含的)选择通过实施要做到这一点构成根您的MVC3项目中(您撰写的对象图的启动路径)。 如果你是非常严格的使用组件保护您的建筑界,您可以将您的成分根或您(MVC)呈现的东西类库。

在第一个选项,你让你的MVC3项目引用这个单独的“引导程序”组件,它会引用其他所有组件在解决方案中加引用您的DI容器库。 这里的问题是,这个引导程序的项目不能引用坐落在MVC3项目类型(因为它会导致循环装配依赖)。 这些类型都被转移到引导程序的项目(即可能需要参考System.Web.Mvc),或者你需要保持容器配置的一小部分,你MVC3应用程序内。 还要注意的是你的MVC项目仍引用其他所有组件间接地通过新的引导程序组件,因为组件的依赖关系是传递的。

虽然将组合物放置根在单独的程序是做有效的事,最DI纯粹的(包括我在内)通常只移动组成根类库当有多个终端应用(即一个Web应用程序+网络服务+ Windows服务)使用相同的业务层。 当我有一个单一的应用程序,我保持组成根我的最终应用中。

第二个选择是从启动项目将所有MVC相关类(视图,控制器等)的类库。 这使得这个新的表示层组件,从应用程序的其余部分留断开。 Web应用程序项目本身将成为一个非常薄的外壳采用了所需的启动逻辑。 Web应用程序项目将是构成根引用的所有其他组件。

提取表示逻辑的类库可以用MVC工作时的事情复杂化。 这将是很难连线了一切,因为控制器和视图,图片,CSS文件等是不是在启动项目。 这可能是可行的,但需要更多的时间来建立。

两个方案各有缺点,这就是为什么我通常建议只保留根组成的web项目。 许多开发人员不希望自己的MVC组件依赖于DAL组装,但是这不是一个真正的问题。 不要忘了,组件是部署构件; 拆分代码成多个组件,以允许代码单独部署。 在另一方面建筑层是一个逻辑工件。 这是非常可能的(普通),以在同一个组装多层。

在这种情况下,我们最终会具有以下组成的根(层),并在同一个Web应用程序项目的表示层(因此在相同的组件)。 而且即使是装配引用包含DAL大会,表示仍然未引用数据访问 。 这是一个很大的区别。

当然,我们这样做的时候,我们失去了编译器检查在编译时这个建筑规则的能力,但是这不应该是一个问题。 大多数建筑规则其实并不能由编译器进行检查,总有一些事情是常识。 如果有一个在你的团队没有常识,你可以随时使用的代码审查(其中每个团队都要IMO总是做的BTW)。 你也可以使用一个工具,如NDepend的(这是商业),它可以帮助您确认您的建筑规则。 当你与你的构建过程集成NDepend的,它可以提醒你,当有人检查代码以违反此类建筑规则。

你可以阅读的成分根在我的书的第四章是如何工作的更详细的讨论依赖注入,原则,实践模式 。



Answer 3:

如果我不使用DI容器,我就不必引用的EntityFramework库在我MVC3应用程序,只有将引用我的DAL /回购层我的业务层。

你可以创建一个名为“DependencyResolver”一个单独的项目。 在这个项目中,你必须引用您的所有库。

现在UI层不需要NHibernate的/ EF或任何其他除了温莎城堡的被引用不相关的UI库。

如果你想从你的UI层隐藏温莎城堡和DependencyResolver你可以写它调用的IoC注册表东西一个HttpModule。

我只为StructureMap的例子:

public class DependencyRegistrarModule : IHttpModule
{
    private static bool _dependenciesRegistered;
    private static readonly object Lock = new object();

    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, args) => EnsureDependenciesRegistered();
    }

    public void Dispose() { }

    private static void EnsureDependenciesRegistered()
    {
        if (!_dependenciesRegistered)
        {
            lock (Lock)
            {
                if (!_dependenciesRegistered)
                {
                    ObjectFactory.ResetDefaults();

                    // Register all you dependencies here
                    ObjectFactory.Initialize(x => x.AddRegistry(new DependencyRegistry()));

                    new InitiailizeDefaultFactories().Configure();
                    _dependenciesRegistered = true;
                }
            }
        }
    }
}

public class InitiailizeDefaultFactories
{
    public void Configure()
    {
        StructureMapControllerFactory.GetController = type => ObjectFactory.GetInstance(type);
          ...
    }
 }

该DefaultControllerFactory不直接使用IoC容器,但它委托给IoC容器的方法。

public class StructureMapControllerFactory : DefaultControllerFactory
{
    public static Func<Type, object> GetController = type =>
    {
        throw new  InvalidOperationException("The dependency callback for the StructureMapControllerFactory is not configured!");
    };

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return base.GetControllerInstance(requestContext, controllerType);
        }
        return GetController(controllerType) as Controller;
    }
}

所述GetController委托在StructureMap登记处(在Windsor它应该是一个安装程序)设置。



Answer 4:

  • 有一种依赖性:如果一个对象实例化另一个对象。
  • 没有依赖性:如果一个对象期望的抽象(构造器注入,方法注入...)
  • 大会引用(引用的DLL,web服务..)是独立的从依赖关系的概念,因为解决一个抽象并能够编译代码,该层必须引用它。


文章来源: Ioc/DI - Why do I have to reference all layers/assemblies in application's entry point?