简体   繁体   English

三层asp.net mvc应用程序中的依赖注入

[英]Dependency Injection in a 3 layer asp.net mvc application

I have a 3 layer application and the layers are: 我有一个3层应用程序,图层是:

  • Web: Presentation Layer (ASP.NET MVC) --> only sees BLL Web:表示层(ASP.NET MVC) - >只看到BLL
  • BLL: Business Logic Layer --> only sees DAL BLL:业务逻辑层 - >只能看到DAL
  • DAL: Data Access Layer DAL:数据访问层

So the Web layer doesn't know anything about my DAL layer. 因此, Web层对我的DAL层一无所知。 I have repository interfaces and concrete classes in my DAL , which are used in BLL layer in business logic classes. 我在DAL有存储库接口和具体类,它们在业务逻辑类的BLL层中使用。 The question is, in order to decouple DAL and BLL , how do I setup Ninject to inject my repository implementations to the BLL layer? 问题是,为了解耦DALBLL ,如何设置Ninject以将我的存储库实现注入BLL层?

The same question is for Web layer and BLL layer, I have interfaces and implementations on BLL which I use them in Web layer, how should I setup Niject for this? 同样的问题是Web层和BLL层,我在BLL上有接口和实现,我在Web层使用它们,我应该如何为此设置Niject?

The idea is that you define interfaces for your DAL and BLL. 我们的想法是为您的DAL和BLL定义接口。 You then take an instance of such an interface as a constructor parameter. 然后,您将此类接口的实例作为构造函数参数。 Example

interface IDatabase
{
    // Methods here
}

Your BLL class: 你的BLL课程:

public class Bll
{
    IDatabase _db;
    public Bll(IDatabase db)
    {
        _db = db;
    }

    public void SomeMethod()
    {
        // Use db here
    }
}

Then in your composition root (in the web application) you use the kernel to configure these dependencies: 然后在组合根(在Web应用程序中)中使用内核来配置这些依赖项:

 kernel.Bind<IDatabase>().To<ConcreteDatabase();

You need the same thing from your controllers to your BLL, but it works the same way. 从控制器到BLL需要相同的东西,但它的工作方式相同。

Apart from that, I think your dependencies are not correctly set up. 除此之外,我认为你的依赖关系没有正确设置。 In general you don't want these vertical dependencies. 通常,您不希望这些垂直依赖项。 You should aim for a flatter hierarchy. 你应该瞄准更平坦的等级制度。 I wrote a blog post about this: http://www.kenneth-truyers.net/2013/05/12/the-n-layer-myth-and-basic-dependency-injection/ 我写了一篇关于此的博客文章: http//www.kenneth-truyers.net/2013/05/12/the-n-layer-myth-and-basic-dependency-injection/

In my blog post I explain what the problem is with such a hierarchy and how you can avoid it. 在我的博客文章中,我解释了这种层次结构的问题是什么以及如何避免它。 Apart from that, it describes exactly your problem: ASP.NET MVC, BLL, DLL and Ninject to tie it together. 除此之外,它描述了你的问题:ASP.NET MVC,BLL,DLL和Ninject将它们联系在一起。

We faced this issue in our enterprise level application as well. 我们在企业级应用程序中也遇到了这个问题。 How do you load up your dependency injection engine with classes from your business and data tiers without creating hard references to the business and data tiers from your web application. 如何使用业务和数据层中的类加载依赖项注入引擎,而无需从Web应用程序创建对业务和数据层的硬引用。 We played with a few designs initially and came up with this very successful design which has worked for us for 18 months in production so far and performs very well. 我们最初玩了一些设计并提出了这个非常成功的设计,到目前为止我们已经为我们工作了18个月并且表现非常好。

In the ninjectwebcommon file in your web application, use reflection to access your business and data tiers so that you can load up everything needed 在Web应用程序的ninjectwebcommon文件中,使用反射来访问业务和数据层,以便您可以加载所需的一切

Like so: 像这样:

        System.Reflection.Assembly assembly;

        assembly = System.Reflection.Assembly.Load("our.biztier");
        kernel.Load(assembly);

        assembly = System.Reflection.Assembly.Load("our.datatier");
        kernel.Load(assembly);

Ninjects "Load" method looks for any class in the assembly which inherits the ninject class "NinjectModule" and then calls it to load everything into the kernel. Ninjects“Load”方法查找程序集中继承ninject类“NinjectModule”的任何类,然后调用它将所有内容加载到内核中。

So our business and data tiers each contain one simple injection class which we use to load up everything. 因此,我们的业务和数据层都包含一个简单的注入类,我们用它来加载所有内容。

public class InjectionModuleBiz : NinjectModule
{


    public override void Load()
    {
        Kernel.Bind<ICustomerBiz>().To<CustomerBiz>().InRequestScope();
        Kernel.Bind<IEmployeeBiz>().To<EmployeeBiz>().InRequestScope();
    }
}

and we have another injectionModule class in our data tier 我们在数据层中有另一个injectModule类

public class InjectionModuleData : NinjectModule
{


    public override void Load()
    {
        Kernel.Bind<ICustomerData>().To<CustomerData>().InRequestScope();
        Kernel.Bind<IEmployeeData>().To<EmployeeData>().InRequestScope();
    }
}

The end result is that all of our business tier and data tier classes are loaded up in our ioc container and can be injected anywhere. 最终结果是我们的所有业务层和数据层类都加载到我们的ioc容器中,并且可以在任何地方注入。

Hope that helps. 希望有所帮助。

I agree there is lots of confusion when we use Dependency injection in N-Tier applications using Visual Studio. 我同意在使用Visual Studio在N层应用程序中使用依赖注入时会有很多困惑。

Mainly because in Visual Studio we structure layers as different projects in a solution and adding the dependencies by referring the project or DLL. 主要是因为在Visual Studio中,我们将层构建为解决方案中的不同项目,并通过引用项目或DLL来添加依赖项。 This is quite different than the principles of DI and Composition Root concepts. 这与DI和Composition Root概念的原理完全不同。

The basic question is what dependencies we are injecting ? 基本问题是我们注入的依赖项是什么?

Business Logic or Repository ? 业务逻辑或存储库?

If it is repository , yes you are right , the web layer need not be knowing about it. 如果它是存储库,是的,你是对的,Web层不需要知道它。 It is the BLL select the repository based on certain conditions. BLL根据特定条件选择存储库。

If we have completely isolated applications we need to set up DI at two levels. 如果我们有完全隔离的应用程序,我们需要在两个级别设置DI。

Your web application will needs to setup ninject to create your BLL components. 您的Web应用程序需要设置ninject来创建BLL组件。 The BLL application will setup ninject to create a specific set of logic and repository classes. BLL应用程序将设置ninject以创建一组特定的逻辑和存储库类。

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

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