【问题标题】:How to tell Ninject to bind to an implementation it doesn't have a reference to如何告诉 Ninject 绑定到它没有引用的实现
【发布时间】:2011-06-05 04:26:24
【问题描述】:

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

我有 3 层

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

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

public class FooService : IFooService
{
    private readonly IFooRepository _fooRepository;

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

    // ...
}

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
}        

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

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-3 dependency-injection ninject separation-of-concerns


【解决方案1】:

为了让你找到正确的方向,我建议你看看onion architecture.

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

如果您愿意接受这一点(我知道,如果您来自经典的 N 层设置,这将是一颗难以下咽的药丸),那么您的情况就会变得简单得多。

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

在你的 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;
    }

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

using Ninject.Modules;

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

并且您对可能拥有的数据层注入重复相同的过程(UnitofWork、DatabaseFactory、IFooRepository 等)

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

现在,您可以预先访问所有需要的绑定。所以,你对我的问题真的归结为思想的转变。如果您可以接受(不情愿地或不情愿地)洋葱概念,那么您的场景就会干净利落地解决。

您也可以查看Project SilkCodeCampServer。他们都在一定程度上实现了“洋葱”的概念(当然,Silk,我现在正在研究解决方案,并且 UI Web 项目包含对包含所有 Repos 的 Data proj 的引用)

让我知道你的想法。

【讨论】:

  • 有趣。我仍然不确定你是否只是想让我被解雇;)但我会考虑这个想法。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多