20

因此,经过一番折腾,我终于将 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 并没有太大帮助:

https://github.com/ninject/ninject/blob/master/src/Ninject/Infrastructure/Language/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.
4

8 回答 8

18

好吧,在我的头撞墙太久之后,我弄清楚发生了什么。在 .NET 4.5 上运行的 MVC4 的默认项目类型引用了 System.Web.Http 的原始 RC 版本,而不是更新版本。

命名空间丢失,对象不存在,生活并不美好。

解决步骤:

  1. 在 MVC4 项目中删除对 System.Web.Http 的引用
  2. 添加参考 -> System.Web.Http
  3. 删除您为使 System.Web.Http 的旧垃圾版本正常工作而投入的所有变通方法
  4. 在 Ninject 中重新应用标准流程进行接线。

    但是,以下错误:

    异常详细信息:Ninject.ActivationException:激活 IntPtr 时出错 没有匹配的绑定可用,并且类型不是自绑定的。激活路径:3)依赖IntPtr注入Func{IKernel}类型构造函数的参数方法2)依赖Func{IKernel}注入HttpApplicationInitializationHttpModule类型构造函数参数lazyKernel 1)请求IHttpModule

    建议: 1) 确保您已为 IntPtr 定义绑定。2) 如果绑定是在模块中定义的,请确保该模块已加载到内核中。3) 确保您没有意外创建多个内核。4) 如果您使用构造函数参数,请确保参数名称与构造函数参数名称匹配。5) 如果您使用自动模块加载,请确保搜索路径和过滤器正确。

更新通过将 MVC 从 MVC4 Beta 更新到 MVC4 RC 解决了这个问题。

于 2012-07-13T13:53:22.237 回答
5

查看Pro ASP.NET MVC 3 书。我昨晚刚刚将此代码从 MVC3 移植到 MVC4 并正常工作。准确地说是第 322 页。

我没有看到您将接口映射到具体项目的位置。

Bind<ISomething>().To<Something>();

添加另一个构造函数并添加调用映射的方法;

public NinjectDependencyResolver() {
    _kernal = new StandardKernel();
    RegisterServices(_kernel);
}

public static void RegisterServices(IKernel kernel) {
    kernel.Bind<ISomething>().To<Something>();
}

这是解析器可能/应该看起来的样子;

   public class NinjectDependencyResolver : IDependencyResolver {
    private IKernal _kernel;

    public NinjectDependencyResolver(){
        _kernal = StandardKernal();
        AddBindings();
    }

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
     {
         return _kernel.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
        return _kernal.GetAll(serviceType);
     }

    public IBindingToSyntax<T> Bind<T>() {
      return _kernal.Bind<T>();
    }

     public static void RegisterServices(IKernel kernel){
      //Add your bindings here. 
      //This is static as you can use it for WebApi by passing it the IKernel
     }
}

全球.Asx -

Application_Start()

方法

DependencyResolver.SetResolver(new NinjectDependencyResolver());

就是这样。


2012 年 11 月 14 日更新

附带说明一下,如果您正在使用 MVC WebAPI,您将需要使用来自nuget的 WebApiContrib.IoC.Ninject。此外,请查看他们的示例asp.net.com中的“联系人管理器” 。这有助于清理 Ninject 的实现

于 2012-07-13T13:09:53.987 回答
4

Just delete NinjectWebCommon.cs file from your project (it is in App_Start folder). and everything should be working.

Source: http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html

于 2014-09-14T14:34:46.403 回答
1

当您从 NuGet 包安装最新的 Ninject.MVC3 时,我们会在NinjectWebCommon.cs文件顶部找到以下代码:

[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]

[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]

在这种情况下,我们不需要在 global.asax 中显式注册 ninject

我在这里找到了关于使用 Ninject 和 MVC 4 的好内容

于 2013-02-02T17:55:56.543 回答
0

我倾向于将我的 Ninject 引导程序放在一个单独的项目中。为了使用 的.InRequestScope()扩展方法IBindingInSyntax<T>,我通过 Nuget 添加了Ninject.Web.Common库。唉,这个库包括 app_start 引导程序,导致重复的 NinjectWebCommon 类和通过 WebActivator 的附件(所述项目中的 1 个,MVC 项目本身中的 1 个)。

我从我的引导项目中删除了重复的 App_Start 文件夹,这解决了它。

于 2013-11-13T23:11:25.150 回答
0

我遇到了同样的问题,不太确定在以下更改后修复了什么

将 Ninject.MVC4 添加到项目中

删除了 NinjectWebCommon.cs(生成的文件,因为集成已经存在于 global.ascx.cs 文件中)

于 2014-04-28T20:41:04.160 回答
0

我正在使用 DD4T,遇到了同样的错误。

在确认所有包都由 nuget 包管理器安装后,我发现缺少一些 DLL/引用(newtonsoft 等):

然后,重新安装 Newtonsoft.Json(要重新安装包,请在 Nuget 包管理器中使用以下命令:Update-Package –reinstall Newtonsoft.Json),并从 Tridion Deployer bin 中放入 netrtsn.dll,我收到此错误 - “Sequence不包含任何元素”,其堆栈跟踪与此问题中给出的完全相同。

感谢 Naga,为提供此解决方案删除了​​ NinjectWebCommon.cs(生成的文件,因为集成已存在于 global.ascx.cs 文件中),哇哦!!!!所有错误都已解决,Tridion + MVC4 = DD4T 现在运行良好。

于 2014-06-12T06:39:03.743 回答
0

当我使用 nuget 在我的实际 MVC 网站项目引用的项目中安装 Ninject.MVC4 时,我也遇到了这个问题。

The trouble is that the NinjectWebCommon.cs file automatically installed in the App_Start directory of the referenced project conflicts with the (actual, useful) one installed in my website project. Removing the NinjectWebCommon.cs file from the referenced project resolves the error.

于 2014-08-15T22:06:42.153 回答