c# - NinjectDependencyResolver 绑定(bind) ModelValidatorProvider 失败

标签 c# ninject ninject.web.mvc

我正在使用 C#、.NET Framework 4.5.1 开发 ASP.NET Web Api 2.2。

将我的 Web.Api 更新为 Ninject 3.2.0 后出现此错误:

Error activating ModelValidatorProvider using binding from ModelValidatorProvider to NinjectDefaultModelValidatorProvider
A cyclical dependency was detected between the constructors of two services.

Activation path:
  3) Injection of dependency ModelValidatorProvider into parameter defaultModelValidatorProviders of constructor of type DefaultModelValidatorProviders
  2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider
  1) Request for ModelValidatorProvider

Suggestions:
  1) Ensure that you have not declared a dependency for ModelValidatorProvider on any implementations of the service.
  2) Consider combining the services into a single one to remove the cycle.
  3) Use property injection instead of constructor injection, and implement IInitializable
     if you need initialization logic to be run after property values have been injected.

我在 NinjectWebCommon 中得到异常:

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        var containerConfigurator = new NinjectConfigurator();
        containerConfigurator.Configure(kernel);
    }        
}

NinjectDependencyResolver 类:

using Ninject;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;

namespace Matt.SocialNetwork.Web.Common
{
    public class NinjectDependencyResolver : IDependencyResolver
    {
        private readonly IKernel _container;

        public IKernel Container
        {
            get { return _container; }
        }

        public NinjectDependencyResolver(IKernel container)
        {
            _container = container;
        }

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

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

        public IDependencyScope BeginScope()
        {
            return this;
        }

        public void Dispose()
        {
            // noop
        }
    }
}

NinjectConfigurator 类:

public class NinjectConfigurator
{
    public void Configure(IKernel container)
    {
        // Add all bindings/dependencies
        AddBindings(container);

        // Use the container and our NinjectDependencyResolver as
        // application's resolver
        var resolver = new NinjectDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }

    // Omitted for brevity.
}

奇怪的是它编译和工作完美,但更新后它不工作。

我已经更改了这个 public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver 但它仍然不起作用。

有什么想法吗?

更新

调试我看到异常在 NinjectDependencyResolver 这里抛出:

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

它运行了两次。第一次 serviceTypeIFilterProvider,第二次 serviceTypeModelValidatorProvider,然后我得到异常。

这些是我正在使用的 Ninject 包:

<package id="Ninject" version="3.2.2.0" targetFramework="net451" />
<package id="Ninject.MVC5" version="3.2.1.0" targetFramework="net45" />
<package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net451" />
<package id="Ninject.Web.Common.WebHost" version="3.2.3.0" targetFramework="net451" />
<package id="Ninject.Web.WebApi" version="3.2.2.0" targetFramework="net451" />

这些程序集的先前版本是:

<package id="Ninject" version="3.2.2.0" targetFramework="net45" />
<package id="Ninject.MVC5" version="3.2.1.0" targetFramework="net45" />
<package id="Ninject.Web.Common" version="3.2.2.0" targetFramework="net451" />
<package id="Ninject.Web.Common.WebHost" version="3.2.0.0" targetFramework="net45" />
<package id="Ninject.Web.WebApi" version="3.2.0.0" targetFramework="net451" />

第二次更新

我发现问题出在这个类中:

public static class WebContainerManager
{
    public static IKernel GetContainer()
    {
        var resolver = GlobalConfiguration.Configuration.DependencyResolver as NinjectDependencyResolver;
        if (resolver != null)
        {
            return resolver.Container;
        }

        throw new InvalidOperationException("NinjectDependencyResolver not being used as the MVC dependency resolver");
    }

    public static T Get<T>()
    {
        return GetContainer().Get<T>();
    }
}

我在这里设置了Dependency Resolver:

public class NinjectConfigurator
{
    /// <summary>
    /// Entry method used by caller to configure the given 
    /// container with all of this application's 
    /// dependencies. Also configures the container as this
    /// application's dependency resolver.
    /// </summary>
    public void Configure(IKernel container)
    {
        // Add all bindings/dependencies
        AddBindings(container);

        // Use the container and our NinjectDependencyResolver as
        // application's resolver
        var resolver = new NinjectDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }

我在继承自 ExceptionFilterAttribute 的类中使用 WebContainerManager:

public class UnhandledExceptionFilter : ExceptionFilterAttribute
{
    private readonly IExceptionLogHelper excepLogHelper;

    public UnhandledExceptionFilter()
        : this(WebContainerManager.Get<IExceptionLogHelper>()) {}

    public UnhandledExceptionFilter(IExceptionLogHelper exceptionLogHelper)
    {
        this.excepLogHelper = exceptionLogHelper;
    }

    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        this.excepLogHelper.LogException(actionExecutedContext);
    }
}

所以,如果我删除 WebContainerManager,我就不会得到那个循环。

最佳答案

在升级 Ninject 包(甚至卸载和删除旧包)后,我对 WebApi2 和 Ninject 初始化感到很痛苦。

特别是在您的情况下,我会删除这些代码行:

// Use the container and our NinjectDependencyResolver as
// application's resolver
var resolver = new NinjectDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;

因为它们可能是错误的原因(NinjectWebCommon.cs 和 Ninject 库现在处理初始化依赖项解析器)。


对于那些遵循与我类似的升级路径的其他人。对我有用的是:

  • 删除旧的 DependencyResolver 初始化代码(对我来说,这导致了您在早期版本的 Ninject/WebApi2 中提到的特定错误,将这些行放在 WebApiConfig.cs Register() 方法中是您初始化 DependencyResolver 的方式...情况不再如此):

    var kernel = new StandardKernel();
    config.DependencyResolver = new NinjectDependencyResolver(kernel);
    
  • 安装 Ninject.Web.WebApi.WebHost 包。这安装了 NinjectWebCommon.cs 文件。对我来说,只要有 Ninject.Web.WebApi 就可以了 依赖项没有创建此文件。

我安装和工作的 Ninject 包供引用:

<package id="Ninject" version="3.2.2.0" targetFramework="net452" />
<package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net452" />
<package id="Ninject.Web.Common.WebHost" version="3.2.0.0" targetFramework="net452" />
<package id="Ninject.Web.WebApi" version="3.2.3.0" targetFramework="net452" />
<package id="Ninject.Web.WebApi.WebHost" version="3.2.3.0" targetFramework="net452" />

关于c# - NinjectDependencyResolver 绑定(bind) ModelValidatorProvider 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26312231/

相关文章:

c# - .net 4.0 任务中的私有(private)变量

c# - 使用 ref 参数委托(delegate)

c# - 仅更新 Entity Framework 6 中的一个字段

c# - 如何创建 LINQ 表达式来调用方法?

c# - Web API Controller 没有默认构造函数。 Ninject 依赖解析器问题

Ninject - 如何动态选择一个实现来绑定(bind)到接口(interface)

asp.net-mvc-3 - 由于 DbContext 已被释放,操作无法完成

asp.net-mvc - Ninject 与基本 Controller ?

asp.net-mvc-3 - 如何阻止 Ninject 覆盖自定义 DataAnnotationsModelValidatorProvider?

asp.net-mvc-4 - 用于 Asp.net Web API 的 Ninject