这个问题与Ninject没有特别的关系。这更像是一个通用的编码问题,但是我在这里发布它,以防有可能在Ninject中处理问题的方式比我想做的更好。
我想知道是否可以从Global.asax中的实例全局访问Ninject标准内核。
以下是代码:
public class MvcApplication : NinjectHttpApplication
{
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
// MVC global registration, routing and filtering code goes here...
}
protected override IKernel CreateKernel()
{
return Container;
}
private static IKernel Container
{
get
{
IKernel kernel = new StandardKernel();
kernel.Load(new ServiceModule(), new RepositoryModule());
return kernel;
}
}
}
如果我有一些类,例如,没有与控制器接口的外观类,我想开始一个依赖链,我的理解是我应该使用:
_className = kernel.Get<IClassName>();
但是,我知道这样做的唯一方法是创建Ninject Standard内核的新实例,但如果我理解正确,那么创建Ninject内核的新实例并不是一个好主意,因为基本上是在创建第二个内核。
那么,是否有可能从我的应用程序中的任何位置访问在Application Start中在Global.asax中实例化的现有内核,或者是否有更好的方法来完成此操作?
此致
弗雷德城堡答案 0 :(得分:25)
最简单的方式(IMO):
_className = (IClassName)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IClassName));
答案 1 :(得分:5)
如果与System.Web.MVC一起使用,则新版本的Ninject具有此方法:
var obj = DependencyResolver.Current.GetService<IClassName>();
除非您需要动态操作DI绑定,但实例化StandardKernel有点重。
IKernel kernel = new StandardKernel();
var obj = DependencyResolver.Current.GetService<IClassName>();
答案 2 :(得分:1)
我设法使服务定位器正常工作,但它似乎运行良好。当请求通过MVC控制器操作方法进入应用程序时,Ninject以Ninject.Mvc.Extensions提供的正常方式运行。它通过控制器构造函数注入实例类。当请求以任何其他方式进入应用程序时,我调用服务定位器来提供该类构造函数中的实例类。
以下是代码:
首先,引用Microsoft.Practices.ServiceLocation
以下Ninject适配器类。
public class NinjectServiceLocator : ServiceLocatorImplBase
{
public IKernel Kernel { get; private set; }
public NinjectServiceLocator(IKernel kernel)
{
Kernel = kernel;
}
protected override object DoGetInstance(Type serviceType, string key)
{
return Kernel.Get(serviceType, key);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
return Kernel.GetAll(serviceType);
}
}
在Global.asax中
public class MvcApplication : NinjectHttpApplication
{
private static IKernel _kernel;
protected override IKernel CreateKernel()
{
return Container;
}
private static IKernel Container
{
get
{
if (_kernel == null)
{
_kernel = new StandardKernel();
_kernel.Load(new ServiceModule(), new RepositoryModule());
ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(_kernel));
}
return _kernel;
}
}
}
请注意,此代码需要使用Ninject.Mvc.Extensions,它为默认控制器提供依赖项解析器回退。否则,可能需要自定义依赖项解析程序。
这似乎解决了我所有的顾虑。它创建实例类,解析整个对象图,并在我需要它工作的任何地方工作。而且,据我所知,每个应用程序只有一个Ninject标准内核。
我知道使用服务定位器模式是不受欢迎的,但我想使用多个Ninject内核会更糟糕。
弗雷德城堡答案 3 :(得分:0)
听起来你需要更多的Ninject工厂模式实现。您可以将内核从Global.asax迁移到Factory类,该类可以与应用程序的其余部分进行交互。
或者,如果您遇到在运行时指定的参数确定接口绑定的情况,则可以包装该服务。这是DI和ServiceLocater的混合设置,但ServiceLocater仅在服务级别实例化时发生,所有其他层通常以DI / IOC模式编码。
MyService : IService1
{
public void DoSomething(MyCustomParameter parameter)
{
//Builds the Kernel using the supplied parameter
//We've in our resolver bound IService1 To MyActualService
var trueService = kernel.Get<IService1>();
return trueService.DoSomething(parameter);
}
}
MyActualService : IService1
{
public void DoSomething()
{
//Do the Actual work
}
}