在3层架构中使用Unity进行依赖注入

时间:2018-01-17 06:18:28

标签: c# asp.net-web-api dependency-injection unity-container 3-tier

我的Web API解决方案有3个项目:控制器层,业务层,数据访问层。 Unity安装在控制器层项目中以实现DI。业务和数据层中的每个类都有一个与之关联的接口。现在我如何从A业务层访问B业务层中的功能,同时遵守DI标准? Unity未安装在业务层项目中。 目前我在做的是:

public class BBusiness
{
    IBDataAccess bDataAccess;
    IADataAccess aDataAccess;

    public BBusiness(IBDataAccess bDataAccessParam, IADataAccess 
    aDataAccessParam)
    {
        this.bDataAccess=bDataAccessParam;
        this.aDataAccess=aDataAccessParam;
    }
    public function()
    {
        ABusiness obj=new ABusiness(this.aDataAccess);
        obj.functionInABusiness();
    }
}

3 个答案:

答案 0 :(得分:0)

据我所知(我是DI的新手),你不应该在ABusiness中创建一个对象BBusiness

你应该做的是像

public function()
{
    aDataAccess.functionInClassThatImplementsInterfaceIADataAccess();
}

您的解决方案意味着,BBusiness仍然依赖于ABusiness,您希望通过使用DI来避免这种情况。

答案 1 :(得分:0)

这是层的整体思路:你不从A中访问B中的函数.A忙于自己的业务,甚至不知道B. B的存在,但是,知道A ,了解A的事件(A提供的任何事件)并对它们做出反应。

答案 2 :(得分:0)

由于ABusiness 某项服务,因此通常会将其设置为:

public interface IABusiness
{
    void functionInABusiness();
}

public class ABusiness : IABusiness
{
    // making the variable private readonly ensures that nothing
    // can set it after the constructor does (thus it can never be null)
    private readonly IADataAccess aDataAccess;

    public ABusiness(IADataAccess aDataAccessParam)
    {
        // Guard clause ensures you cannot set this.aDataAccess to null
        if (aDataAccessParam == null)
            throw new ArgumentNullException(nameof(aDataAccessParam));
        this.aDataAccess=aDataAccessParam;
    }

    public void functionInABusiness()
    {
        // Do something with aDataAccess
    }
}

然后,您将添加IABusiness作为BBusiness的依赖项。

public interface IBBusiness
{
    void function();
}

public class BBusiness : IBBusiness
{
    private readonly IBDataAccess bDataAccess;
    private readonly IABusiness aBusiness;

    public BBusiness(IBDataAccess bDataAccessParam, IABusiness aBusinessParam)
    {
        if (bDataAccessParam == null)
            throw new ArgumentNullException(nameof(bDataAccessParam));
        if (aBusinessParam == null)
            throw new ArgumentNullException(nameof(aBusinessParam));
        this.bDataAccess=bDataAccessParam;
        this.aBusiness=aBusinessParam;
    }
    public function()
    {
        this.aBusiness.functionInABusiness();
        // Do something else...
    }
}

composition root中,您可以设置Unity将IABusinessABusinessIBBusinessBBusiness相关联。请注意,如果类和接口以某种方式命名或放在某个位置等,某些项目会使用自动执行此步骤的约定。

container.RegisterType<IABusiness, ABusiness>();
container.RegisterType<IBBusiness, BBusiness>();
container.RegisterType<IADataAccess, ADataAccess>();
container.RegisterType<IBDataAccess, BDataAccess>();

整个想法是您不直接从ABusiness类引用BBusiness类,因此您可以将IABusiness的不同实例注入BBusiness(对于测试,或创建围绕IABusiness的装饰器类,增加了对它的额外责任等。)

此外,IABusiness接口可能与ABusiness不同的程序集(例如),因此BBusiness程序集不需要引用ABusiness程序集

  

请注意,您没有关注Microsoft的capitalization conventions,这可能会使跟踪您的代码难以维护。方法名称应该是.NET中的Pascal大小写,如FunctionInABusiness()