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

发布于 2024-11-14 10:32:48 字数 848 浏览 1 评论 0原文

我在 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 依赖项?

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

I have 3 layers

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

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

public class FooService : IFooService
{
    private readonly IFooRepository _fooRepository;

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

    // ...
}

NinjectMVC3 executes this bootstrapping method in the Foo.Web startup

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红焚 2024-11-21 10:32:48

为了让您指明正确的方向,我建议您查看 洋葱架构。

它的基本前提是任何代码都可以依赖于更中心的层。在您的场景中(这是使用存储库模式的 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 dropin)并添加我所说的内容在 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 项目包含对包含所有存储库的 Data 项目的引用)

让我知道您的想法。

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.

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.

With Ninject you now do something as follows:

In your NinjectMVC3.cs file your CreateKernel becomes

    /// <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:

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.)

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)

Let me know what you think.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文