Bootstrapping Unity - 组合根位置

时间:2016-11-03 12:47:03

标签: .net dependency-injection unity-container

我有一个简单的.NET项目,我想知道什么是引导Unity的最佳方法。 我开始使用带有一堆控制器的WebApp。每个控制器都有自己的Handler类,控制器委托实现。有些东西:

public class UsersHandler : IUsers
{
    IAuthenticationClient authenticationClient;
    ILogger logger;

    public UsersHandler(IAuthenticationClient authClient, ILogger logger) { ... }       
}

在Global.asax的Application_Start方法中,我正在创建UnityContainer并注册类型。 还有第二个项目(类库),它基本上是业务层。

我现在创建了一个新的类库(让我们称之为'XYZ')来处理应用程序的不同责任。 DI也在这里使用。

enter image description here

对于初学者,我创建了一个Singleton类,它将作为此项目的入口点,我将实例化UnityContainer和寄存器类型。

现在我已经开始工作,我开始想知道谁应该处理类型注册,这意味着应该是我的应用程序的组合根。 WebApp将是第一选择,但这需要添加对'XYZ'项目的引用,因为业务层使用它,所以感觉不对。

1)Composition根应该是一个引用WebApp和'XYZ'并在我的WebApp的global.asax中初始化的新类库吗? 但是,这会导致循环依赖,因为此Bootstrapper项目将知道WebApp,反之亦然。

2)如果我需要在'XYZ'项目中解决依赖关系怎么办?目前我有一个UnityContainer类的实例,所以我能够这样做:

var logger = container.Resolve<ILogger>();

这是一个好的做法吗?

2 个答案:

答案 0 :(得分:3)

喜欢this很棒的回答说

  

&#34;应用程序中的所有组件应该最晚组成   可能&#34;

然后你应该在WebApp项目的global.asax中组合它们。 所有这些(基本上回答了这两个问题)。

组合根是应用程序中所有模块组合的地方。 在您的情况下,WebApp将成为该项目,因此应该参考解决方案中的所有项目。 WebApp应该引用Business Layer,XYZ和您添加的所有其他项目。

  

&#34;但是,这会导致循环依赖。&#34;

不,只有合成根指的是解决方案中的项目。

但是业务层和XYZ如何相互协作呢?

他们没有。 DIP的核心原则是依赖于抽象,并在您的解决方案中充分使用DIP,您需要正确设计代码。

假设我们在业务层项目中有一个对XYZ项目具有依赖性的类

using XYZ;
namespace BusinessLayer
{
    public class businessData
    {
        public int GetData()
        {
            var data = new XYZData(); //from the XYZ project
            return data
        }
    }
}

这个类在XYZ项目中

namespace XYZ
{
    public class XYZData
    {
        public int GetData()
        {
            return 1;
        }
    }
}

现在我们拥有项目BusinessLayer和XYZ之间的依赖关系。 为了解决这个问题,我们需要使BusinessLayer中的businessData依赖于抽象而不是细节。

要做到这一点,我们需要使用Interfaces来消除类之间的依赖关系,并且当它们被处理时,我们不需要在BusinessLayer项目中引用XYZ,因为它&#39;不再使用了。

但我们在哪里存储界面?

为此,您将创建一个ModelProject,解决方案中的所有项目都将引用该模型。 ModelProject不涉及任何东西,因为它的目的是仅存储DTO和接口等。

解决方案中的引用应该是这样的(抱歉我的绘画技巧):enter image description here

作为组合根的WebApp应该引用解决方案中的所有项目。其余项目应仅参考ModelProject

要解决businessData中的依赖性,请将此接口添加到Modelproject

namespace Modelproject
{
    public interface IXYZData
    {
        int GetData();
    }
}

然后在类

中实现接口

对于商业项目

using Modelproject;
namespace BusinessLayer
{
    public class businessData
    {
        private IXYZData _data;
        public businessData(IXYZData data)
        {
            this._data = data;
        }

        public int GetData()
        {
            return _data.GetData();
        }
    }
}

对于XYZ项目

using Modelproject;
namespace XYZ
{
    public class XYZData: IXYZData
    {
        public int GetData()
        {
            return 1;
        }
    }
}

然后在WebApp的global.asax中,使用XYZData类解析接口IXYZData。 通过Unity将是

var container = new UnityContainer();
container.RegisterType<IXYZData, XYZData>(new HierarchicalLifetimeManager());
GlobalConfiguration.Configuration.DependencyResolver = new UnityResolver(container);

希望这会有所帮助,欢呼

<强>更新

如果要在另一个类中使用businessData类,则应该应用与添加接口的XYZData类相同的结构。

namespace Modelproject
{
    public interface IbusinessData
    {
        int GetData();
    }
}

然后将接口继承添加到类

using Modelproject;
namespace BusinessLayer
{
    public class businessData: IbusinessData
    {
    .....

最后告诉Global.asax中的Unity容器解析类

的接口
container.RegisterType<IbusinessData, businessData>(new HierarchicalLifetimeManager());

现在,在您需要使用IbusinessData的每个类中,将它添加到类的构造函数中,就像我们在businessData构造函数中所做的那样,然后Unity将确保在运行时创建该类时注入所有依赖项。

答案 1 :(得分:0)

  1. 您应该在启动方法
  2. 中执行此操作一次
  3. 您可以实施Unity Dependency解析器,也不要执行container.Resolve<IDependency>()
  4. 之类的代码

    你可以在这里阅读一篇非常好的文章https://www.asp.net/web-api/overview/advanced/dependency-injection