我对IoC框架很陌生,所以请原谅这个术语。
所以我所拥有的是一个带有Nininject MVC参考的MVC项目。
我的项目中有其他类libarys,例如域层,我希望能够在那里使用Ninject框架,但我的所有绑定都在MVC项目的NinjectWebCommon.cs
文件夹下的App_Start
中:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHardwareService>().To<WindowsHardwareService>();
kernel.Bind<IStatusApi>().To<StatusApiController>();
}
目前在我的类库中我正在使用构造函数注入,但有时我不得不对依赖项进行硬编码:
var service = new WindowsHardwareService();
当我希望能够执行以下操作时:
IKernel kernel = new StandardKernel(.....);
var context = kernel.Get<IHardwareService>();
我没有做以下因为我没有任何模块? 我读过的所有文档主要针对的是常规Ninject库而不是MVC版本。
我需要做什么,如何将常规Ninject库与MVC版本一起使用?
更新
这就是我的尝试:
这样做的目的是使每个项目都可以加载模块并获得当前注入的接口。
App_Start / NinjectWebCommon.cs (在MVC项目中)
private static void RegisterServices(IKernel kernel)
{
var modules = new IoCModules();
var newKernal = modules.GetKernel();
kernel = newKernal;
}
IoCModules.cs (在Project.Ioc项目中)
public class IoCModules
{
public IKernel GetKernel()
{
var modules = new CoreModule();
return modules.Kernel;
}
}
CoreModule.cs (在Project.IoC.Modules项目中)&lt; - 这是所有项目的所有引用所在,这可以解决任何循环依赖问题。
public class CoreModule : NinjectModule
{
public override void Load()
{
Bind<IHardwareService>().To<WindowsHardwareService>();
Bind<IStatusApi>().To<StatusApiController>();
}
}
但我现在得到以下内容:
激活IHardwareService时出错
没有匹配的绑定可用,并且该类型不可自我绑定。 激活路径:
2)将依赖关系IHardwareService注入到DashboardController类型的构造函数的参数服务中
1)请求DashboardController
建议:
1)确保您已为IHardwareService定义了绑定。
2)如果在模块中定义了绑定,请确保已将模块加载到内核中。
3)确保您没有意外创建多个内核。
4)如果使用构造函数参数,请确保参数名称与构造函数参数名称匹配。
5)如果使用自动模块加载,请确保搜索路径和过滤器正确无误。
答案 0 :(得分:19)
您似乎有很多问题需要在这里解答,所以我会尽力做到最好。
根据您当前的问题,我将尝试“制定”您当前实施的简化架构:
WindowsHardwareService
DependencyResolution
程序集。假设上述所有情况,我们可以声明您的应用Composition Root
或Entry point
是 UI MVC项目。使用DI Container
的主要概念之一是您在Composition Root
设置/在此处执行所有需要的绑定和注册。在入口点执行此操作的主要目的是避免使用Service Locator
反模式。
使用DI Container
你没有new()
你的类实现或获取内核而是要求注册的依赖项,遵循Inversion Of Control
的规则或者也称为好莱坞原则。
在哲学课程之后,我们终于可以实现一些实际的实施。
在 IOC 程序集中创建Ninject module ,我们可以将此文件称为ServiceModule.cs
using Ninject.Modules;
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IHardwareService>().To<WindowsHardwareService>();
Bind<IStatusApi>().To<StatusApiController>();
}
}
这将是您在Ninject module
注册/加载的Composition Root
。
现在关于 UI MVC项目NinjectWebCommon.cs
中的撰写根
您可以使用负责加载模块的方法,如下所示。
private static void RegisterServices(IKernel kernel)
{
var modules = new List<INinjectModule>
{
new ServiceModule()
//, new FooModule()
//, new BarModule()
};
kernel.Load(modules);
}
最后是 UI MVC中的DashboardController
:
public class DashboardController : Controller
{
private readonly IHardwareService _hardwareService;
public DashboardController(IHardwareService hardwareService)
{
_hardwareService = hardwareService;
}
}
此时,您要求在控制器构造函数中注册IHardwareService
的实现。 DI Container
将执行脏作业并将您稍后可以在控制器中使用的实例传递给您。
关于接口的说明:我倾向于将这些放入自己的程序集中,我只存储接口,例如:Project.Domain.Interfaces
或Project.Infrastructure.Interfaces
其中每个接口程序集仅包含域或基础结构接口。
程序集之间的引用:
要将所有这些放在一起, UI 仅引用 IOC 程序集和接口程序集,其中包含您绑定在{{{ 1}}。
总结以上所有内容:
你自己的类和接口只是DI容器一起粘合的部分。
希望我清理一下。
编辑:作为 @AndreySarafanov 在评论中指出的一些好建议,如果你需要在构造函数中要求的接口的不同实现,你可以使用Ninject Factory。有关详细信息,请参阅this answer。