如何告诉Ninject绑定到它没有引用的实现

时间:2022-09-29 07:18:46

I'm using NinjectMVC3 in my ASP.NET MVC3 project.

我在我的ASP.NET MVC3项目中使用NinjectMVC3。

I have 3 layers

我有3层

  • Foo.Web
  • Foo.Web
  • Foo.Services
  • Foo.Services
  • Foo.Data
  • Foo.Data

Foo.Web references Foo.Services but not Foo.Data. One of my services looks like this

Foo.Web引用Foo.Services但不引用Foo.Data。我的一个服务看起来像这样

public class FooService : IFooService
{
    private readonly IFooRepository _fooRepository;

    public FooService(IFooRepository fooRepository)
    {
        _fooRepository = fooRepository;
    }

    // ...
}

NinjectMVC3 executes this bootstrapping method in the Foo.Web startup

NinjectMVC3在Foo.Web启动时执行此引导方法

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IFooService>().To<FooService>();
    kernel.Bind<IFooRepository>().To<FooRepository>();
    // Foo.Web doesn't know what FooRepository is
}        

How can I inject FooServices dependencies from Foo.Web?

如何从Foo.Web注入FooServices依赖项?

1 个解决方案

#1


7  

To get you pointed in the right direction, I'd suggest you take a look at the onion architecture.

为了让你指出正确的方向,我建议你看看洋葱建筑。

It's basic premise is that any code can depend on layers more central. In your scenario (and it's a common one for MVC3 apps using the Repository pattern) your UI should have a reference to the services layer and it's acceptable to have a reference to the data layer.

它的基本前提是任何代码都可以依赖于更加集中的层。在您的场景中(对于使用Repository模式的MVC3应用程序而言,它是常见的),您的UI应该具有对服务层的引用,并且可以接受对数据层的引用。

If you're willing to accept that (it's a hard pill to swallow if you're coming from a classic N-tier setup, I know), then your situation becomes much simpler.

如果你愿意接受(如果你来自经典的N层设置,这是一个难以吞下的药丸,我知道),那么你的情况变得更加简单。

With Ninject you now do something as follows:

使用Ninject,您现在可以执行以下操作:

In your NinjectMVC3.cs file your CreateKernel becomes

在您的NinjectMVC3.cs文件中,您的CreateKernel变为

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var modules = new INinjectModule[]
                          {
                              new ServiceDIModule(),
                              new RepositoryDIModule()
                          };

        var kernel = new StandardKernel(modules);

        //RegisterServices(kernel); <-- Only if you have some custom binding 
        //                              that are UI specific
        return kernel;
    }

Now, in your services layer, you add a reference to Ninject (just plain Ninject via NuGet, not the MVC3 dropin via NuGet) and add what I called above the ServiceDIModule which looks like this:

现在,在您的服务层中,添加对Ninject的引用(通过NuGet只是简单的Ninject,而不是通过NuGet的MVC3 dropin),并添加我在ServiceDIModule上面调用的内容,如下所示:

using Ninject.Modules;

namespace MyServiceLayer
{
    public class ServiceDIModule : NinjectModule
    {
        public override void Load()
        {
            //Bind Services
            Bind<IPracticeService>().To<PracticeService>().InRequestScope();
        }
    }
}

and you repeat the same process for the Data Tier injections you may have (UnitofWork, DatabaseFactory, IFooRepository, etc.)

并重复相同的数据层注入过程(UnitofWork,DatabaseFactory,IFooRepository等)

namespace MyDataLayer
{
    public class RepositoryDIModule : NinjectModule
    {
        public override void Load()
        {
            //Bind Repos
            Bind<IFooRepository>().To<FooRepository>().InRequestScope();
        }
    }
}

Now, you have access to all of the bindings you need way upfront. So, your question to me really boils down to a shift in thinking. If you can accept (begrudgingly or otherwise) the onion concept, your scenario resolves itself cleanly.

现在,您可以预先访问所需的所有绑定。所以,你对我的问题实际上归结为思维的转变。如果您可以接受(不情愿或其他方式)洋葱概念,您的方案将干净利落地解决。

You can also check out Project Silk and CodeCampServer. They both implement the "onion" concept to some degree (Silk for sure, I'm looking at the solution right now and the UI web project contains a ref to the Data proj which contains all the Repos)

您还可以查看Project Silk和CodeCampServer。他们都在某种程度上实现了“洋葱”概念(Silk肯定,我现在正在寻找解决方案,UI web项目包含对包含所有Repos的Data proj的引用)

Let me know what you think.

让我知道你的想法。

#1


7  

To get you pointed in the right direction, I'd suggest you take a look at the onion architecture.

为了让你指出正确的方向,我建议你看看洋葱建筑。

It's basic premise is that any code can depend on layers more central. In your scenario (and it's a common one for MVC3 apps using the Repository pattern) your UI should have a reference to the services layer and it's acceptable to have a reference to the data layer.

它的基本前提是任何代码都可以依赖于更加集中的层。在您的场景中(对于使用Repository模式的MVC3应用程序而言,它是常见的),您的UI应该具有对服务层的引用,并且可以接受对数据层的引用。

If you're willing to accept that (it's a hard pill to swallow if you're coming from a classic N-tier setup, I know), then your situation becomes much simpler.

如果你愿意接受(如果你来自经典的N层设置,这是一个难以吞下的药丸,我知道),那么你的情况变得更加简单。

With Ninject you now do something as follows:

使用Ninject,您现在可以执行以下操作:

In your NinjectMVC3.cs file your CreateKernel becomes

在您的NinjectMVC3.cs文件中,您的CreateKernel变为

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var modules = new INinjectModule[]
                          {
                              new ServiceDIModule(),
                              new RepositoryDIModule()
                          };

        var kernel = new StandardKernel(modules);

        //RegisterServices(kernel); <-- Only if you have some custom binding 
        //                              that are UI specific
        return kernel;
    }

Now, in your services layer, you add a reference to Ninject (just plain Ninject via NuGet, not the MVC3 dropin via NuGet) and add what I called above the ServiceDIModule which looks like this:

现在,在您的服务层中,添加对Ninject的引用(通过NuGet只是简单的Ninject,而不是通过NuGet的MVC3 dropin),并添加我在ServiceDIModule上面调用的内容,如下所示:

using Ninject.Modules;

namespace MyServiceLayer
{
    public class ServiceDIModule : NinjectModule
    {
        public override void Load()
        {
            //Bind Services
            Bind<IPracticeService>().To<PracticeService>().InRequestScope();
        }
    }
}

and you repeat the same process for the Data Tier injections you may have (UnitofWork, DatabaseFactory, IFooRepository, etc.)

并重复相同的数据层注入过程(UnitofWork,DatabaseFactory,IFooRepository等)

namespace MyDataLayer
{
    public class RepositoryDIModule : NinjectModule
    {
        public override void Load()
        {
            //Bind Repos
            Bind<IFooRepository>().To<FooRepository>().InRequestScope();
        }
    }
}

Now, you have access to all of the bindings you need way upfront. So, your question to me really boils down to a shift in thinking. If you can accept (begrudgingly or otherwise) the onion concept, your scenario resolves itself cleanly.

现在,您可以预先访问所需的所有绑定。所以,你对我的问题实际上归结为思维的转变。如果您可以接受(不情愿或其他方式)洋葱概念,您的方案将干净利落地解决。

You can also check out Project Silk and CodeCampServer. They both implement the "onion" concept to some degree (Silk for sure, I'm looking at the solution right now and the UI web project contains a ref to the Data proj which contains all the Repos)

您还可以查看Project Silk和CodeCampServer。他们都在某种程度上实现了“洋葱”概念(Silk肯定,我现在正在寻找解决方案,UI web项目包含对包含所有Repos的Data proj的引用)

Let me know what you think.

让我知道你的想法。