因此,经过一番折腾,我终于将 Ninject 连线并在我的 MVC4 应用程序中编译。我遇到的问题是 IDependencyScope 接口不再存在,并且 System.Web.Http.Dependencies 命名空间已被取消。
所以,我现在的问题是我已经连接了所有东西,并且在运行我得到的应用程序时:
Sequence contains no elements
[InvalidOperationException: Sequence contains no elements]
System.Linq.Enumerable.Single(IEnumerable`1 source) +379
Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:53
Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:52
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:31
Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:53
Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\NinjectHttpApplication.cs:81
我无法追踪甚至无法开始了解它的来源。
我在 Global.asax.cs 中的标准 Ninject 方法如下所示:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
}
还有我的自定义解析器:
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
public void Dispose()
{
// When BeginScope returns 'this', the Dispose method must be a no-op.
}
}
这里的任何见解将不胜感激。我已经花了太多时间试图将任何 DI 框架连接到在 .NET 4.5 上运行的最新 MVC4 RC 中,现在刚刚达到了我对根本不工作的容忍度。
编辑 #1 在 github 中深入研究 ExtensionsForIEnumerableOfT.cs 并没有太大帮助:
如果我自己写的话,我可能会开始理解这一点,但 Bootstrapper.cs 也没有太大帮助。
https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs
希望这些细节能让任何对 Ninject 有更多经验的人更容易。
编辑 #2 遇到的错误专门在 NinjectMvcHttpApplicationPlugin.cs 中:
违规行是:
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
采用以下方法:
public void Start()
{
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
DependencyResolver.SetResolver(this.CreateDependencyResolver());
RemoveDefaultAttributeFilterProvider();
}
ModelValidatorProviders 集合包含 2 个元素: {System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}
它正在尝试删除以下单个实例:
System.Web.Mvc.DataAnnotationsModelValidatorProvider
这显然没有加载到 ModelValidationProviders.Providers 集合中。从这里有什么想法吗?
解决上述异常并进入下一个
为了解决 ModelValidatorProviders 中的问题,我必须手动添加它所期望的对象。所以现在我的 CreateKernel 方法看起来像:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
kernel.Unbind<IDocumentViewerAdapter>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
return kernel;
}
现在它运行并进入了 Ninject 的实际内容,但仍然有一个问题,一个又没有意义的问题:
Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
1) Request for IHttpModule
Suggestions:
1) Ensure that you have defined a binding for IntPtr.
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.