使用Nininject MVC与类库 [英] Using Nininject MVC with class libraries

查看:102
本文介绍了使用Nininject MVC与类库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很新的国际奥委会框架,所以请原谅的术语。

所以,我有什么与Nininject MVC引用一个MVC项目。
我还有其他类libarys在我的项目例如领域层,我想是能够使用Ninject框架在那里,但我所有的绑定都是在 NinjectWebCommon.cs App_Start 中的MVC项目文件夹:

 私有静态无效RegisterServices(内核的iKernel)
{
    kernel.Bind&所述; IHardwareService方式>()到< WindowsHardwareService>();
    kernel.Bind&所述; IStatusApi方式>()到< StatusApiController>();
}

目前在我的类库我使用构造器注入但是有时候,我有硬code的依赖关系:

  VAR的服务=新WindowsHardwareService();

当我想能够做到以下几点:

 的iKernel内核=新StandardKernel(.....);
VAR背景= kernel.Get< IHardwareService>();

我还没有被执行以下操作,因为我没有任何模块?
所有我看过的文档主要是针对普通Ninject库,而不是MVC的版本。

什么是我需要做的,我怎么可以使用常规的Ninject库与MVC版本?

更新

这是我曾尝试:

这样做的目的是使每一个项目都可以加载模块并获得当前注入的接口。

App_Start / NinjectWebCommon.cs (在MVC项目)

 私有静态无效RegisterServices(内核的iKernel)
{
    VAR模块=新IoCModules();
    变种newKernal = modules.GetKernel();    内核= newKernal;
}

IoCModules.cs (在Project.Ioc项目)

 公共类IoCModules
{
    公众的iKernel GetKernel()
    {
        VAR模块=新CoreModule();
        返回modules.Kernel;
    }
}

CoreModule.cs (在Project.IoC.Modules项目)LT; - 这是所有的地方所有项目的引用,这让周围的任何循环依赖问题的

 公共类CoreModule:NinjectModule
{
    公共覆盖无效负载()
    {
       绑定&所述; IHardwareService方式>()到< WindowsHardwareService>();
       绑定&所述; IStatusApi方式>()到< StatusApiController>();
    }
}

但我目前得到以下内容:


  

错误激活IHardwareService


  
  

没有匹配的绑定是可用的,并且类型不是自我绑定。
  激活路径:


  
  

2)的依赖IHardwareService注射入式DashboardController的构造函数参数服务


  
  

1)请给DashboardController


  
  

建议:


  
  

1)确保您已经定义了IHardwareService绑定。


  
  

2)如果一个模块中定义的结合,确保模块已被加载到内核中。


  
  

3)确保你不小心创建了多个内核。


  
  

4)如果你使用的是构造函数的参数,确保参数名称参数构造函数名称相匹配。


  
  

5)如果你使用的是自动加载模块,保证了搜索路径和过滤器是正确的。



解决方案

看来你有很多需要在这里得到解答什么问题,所以我会尽力做到最好。

根据您当前的问题,我会尝试制定您目前执行的一个简化的架构:


  • 域层:您的域名,将您的商业实体等核心

  • 基础设施层:这是您的服务驻留例如: WindowsHardwareService

    • 国际奥委会:我倾向于这个称呼其为 DependencyResolution 组装


  • UI: MVC应用程序

假设这一切之上,我们可以说,你的应用程序的 构成根 入口点 UI MVC项目。主要概念之一使用 DI容器那是你initalize它在构成根设置/做你的所需的绑定和注册在这里。主要的意图去做的入口点是为了避免 服务定位器 反模式。

通过使用 DI容器你不这样做新()你的类实现或得到内核,但而索要注册的依赖,以下 反转的控制权 或也被称为好莱坞原则。

后哲学过程中,我们终于可以得到一些实际的实现。

创建 Ninject模块:在您< STRONG>国际奥委会装配,让调用这个文件作为 ServiceModule.cs

 使用Ninject.Modules;
公共类ServiceModule:NinjectModule
{
    公共覆盖无效负载()
    {
        绑定&所述; IHardwareService方式&gt;()到&lt; WindowsHardwareService&GT;();
        绑定&所述; IStatusApi方式&gt;()到&lt; StatusApiController&GT;();
    }
}

这将是 Ninject模块,你将注册/负载在构成根

现在谈谈成分根: UI MVC项目 NinjectWebCommon.cs
你可以有一个负责加载你的模块下面的方法。

 私有静态无效RegisterServices(内核的iKernel)
{
    VAR模块=新的List&LT; INinjectModule&GT;
        {
            新ServiceModule()
            //,新FooModule()
            //,新BarModule()
        };    kernel.Load(模块);
}

最后你的 DashboardController 中的 UI 的MVC:

 公共类DashboardController:控制器
{
    私人只读IHardwareService _hardwareService;    公共DashboardController(IHardwareService hardwareService)
    {
        _hardwareService = hardwareService;
    }
}

在这一点上,你的要求在控制器构造函数中执行注册 IHardwareService 的。在 DI容器将做肮脏的工作,并通过你,你可以在以后在你的控制器的工作实例。

有关接口的说明:我倾向于把这些变成一个自己的装配,在这里我只存储接口,例如: Project.Domain.Interfaces Project.Infrastructure.Interfaces 其中每个组件只包含域或基础设施的接口。

组件之间的参考文献:

把所有这些一起在 UI 只引用国际奥委会组装和在接口大会,containts你在你的<$绑定的接口C $ C> Ninject模块。

总结以上所有的:

您的类和亲自过问单独的接口只是个什么都得到的粘贴的由DI容器在一起。

我希望它清理了一下。

编辑:作为 @AndreySarafanov 在评论中指出,如果你需要你在构造函数中要求一个接口的不同实现,你可以使用一些好的建议 Ninject厂的。欲了解更多信息,您可以参阅这个答案。

I'm quite new to IoC frameworks so please excuse the terminology.

So what I have is a MVC project with the Nininject MVC references. I have other class libarys in my project e.g. Domain layer, I would like to be able to use the Ninject framework in there but all of my bindings are in the NinjectWebCommon.cs under the App_Start folder in the MVC project:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IHardwareService>().To<WindowsHardwareService>();
    kernel.Bind<IStatusApi>().To<StatusApiController>();
}

Currently in my class library I am using constructor injection but sometime I am having to hardcode the dependencies:

var service = new WindowsHardwareService();

When I would like to be able to do the following:

IKernel kernel = new StandardKernel(.....);
var context = kernel.Get<IHardwareService>();

I have not been doing the following because I do not have any modules? All of the documentation I have read is mainly aimed at the regular Ninject library and not the MVC version.

What do I need to do, and how can I use the regular Ninject library with the MVC version?

Update

This is what I have tried:

The aim of this is so that each project can load the module and get the current injected interface.

App_Start/NinjectWebCommon.cs (In MVC Project)

private static void RegisterServices(IKernel kernel)
{
    var modules = new IoCModules();
    var newKernal = modules.GetKernel();

    kernel = newKernal;
}

IoCModules.cs (In Project.Ioc project)

public class IoCModules
{
    public IKernel GetKernel()
    {
        var modules = new CoreModule();
        return modules.Kernel;
    }
}

CoreModule.cs (In Project.IoC.Modules project) <-- This is where all the references to all projects are, this get's around any circular dependency issues.

public class CoreModule : NinjectModule
{
    public override void Load()
    {
       Bind<IHardwareService>().To<WindowsHardwareService>();
       Bind<IStatusApi>().To<StatusApiController>();
    }
}

But I am currently getting the following:

Error activating IHardwareService

No matching bindings are available, and the type is not self-bindable. Activation path:

2) Injection of dependency IHardwareService into parameter service of constructor of type DashboardController

1) Request for DashboardController

Suggestions:

1) Ensure that you have defined a binding for IHardwareService.

2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.

3) Ensure you have not accidentally created more than one kernel.

4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.

5) If you are using automatic module loading, ensure the search path and filters are correct.

解决方案

It seems that you have a lot of questions what needs to be answered here, so I will try to do my best.

Based on your current question I will try to "draw up" a simplified architecture of your current implementation:

  • Domain layer: The core of your domain, place of your business entities, etc.
  • Infrastructure layer: This is where your services reside e.g.: WindowsHardwareService
    • IOC: I tend to call to this as DependencyResolution assembly.
  • UI: MVC application

Assuming this all above, we can state that your applications Composition Root or Entry point is the UI MVC project. One of the main concepts using a DI Container that is you initalize it in the Composition Root set up/do all your needed bindings and registrations here. The main intention to do it in the entry point is to avoid the Service Locator anti-pattern.

By using a DI Container you don't new() up your class implementations or get the kernel but rather ask for the registered dependency, following the rule of Inversion Of Control or also known as the Hollywood principle.

After the philosphy course, we can finally get to some actual implementation.

Creating an Ninject module: in your IOC assembly, lets call this file as ServiceModule.cs

using Ninject.Modules;
public class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IHardwareService>().To<WindowsHardwareService>();
        Bind<IStatusApi>().To<StatusApiController>();
    }
}

This will be the Ninject module that you will register/load in the Composition Root.

Now about the Composition Root: in UI MVC projects NinjectWebCommon.cs You can have a method that is responsible loading your modules as below.

private static void RegisterServices(IKernel kernel)
{
    var modules = new List<INinjectModule>
        {
            new ServiceModule()
            //, new FooModule()
            //, new BarModule()
        };

    kernel.Load(modules);
}  

And finally your DashboardController in UI MVC:

public class DashboardController : Controller
{
    private readonly IHardwareService _hardwareService;

    public DashboardController(IHardwareService hardwareService)
    {
        _hardwareService = hardwareService;
    }
}

At this point, your ask for the registered implementation of IHardwareService in the controllers constructor. The DI Container will do the dirty job and pass you the instance that you can work with later in your controller.

A note about the interfaces: I tend to put these into an own assembly, where I just store the interfaces, e.g.: Project.Domain.Interfaces or Project.Infrastructure.Interfaces where each of these assemblies contain only domain or infrastructure interfaces.

References between assemblies:

To put all these together the UI only references the IOC assembly and the interfaces assembly that containts the interfaces you bound in your Ninject Module.

Summarizing all of the above:

Your classes and interfaces alone by theirselves are just pieces what are getting glued together by the DI container.

Hope I cleared it up a bit.

EDIT: as some good advice that @AndreySarafanov pointed out in comments, if you need different implementations of an interface you ask for in the constructor, you can use a Ninject Factory. For more information you can refer to this answer.

这篇关于使用Nininject MVC与类库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆