web-dev-qa-db-ja.com

NinjectDependencyResolverがModelValidatorProviderのバインドに失敗する

私は、ASP.NET Web Api 2.2とC#、. NET Framework 4.5.1を開発しています。

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);
}

2回実行されます。最初のserviceTypeIFilterProviderで、2回目の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" />

2回目の更新

問題はこのクラスにあることがわかりました:

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;
    }

そして、WebContainerManagerを継承するクラスでExceptionFilterAttributeを使用します。

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を削除すると、そのサイクルが得られません。

29
VansFannel

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" />
13
mips

古いNinjectまたはNinject.Web.Common.* dllがbinフォルダーに存在しないことを確認してください。

Ninject.Web.CommonNinject.Web.Common.WebHostNinject.Web.WebApi、およびNinject.MVC5をNugetからアンインストールし、WebApiContrib.IoC.NinjectをインストールしてGlobalConfiguration.Configuration.DependencyResolverをインストールした後も、同じ問題がソリューションで発生しました[SOMECODE] _例のように。私は既にインストールしたNinjectのバージョンを保持しました(実際に .2.2 でした)。

最初に変更を加えたとき、エラーは表示されませんでした。しかし、いくつかのgitブランチから現在の作業に戻った後、エラーが発生しました。先週正常に実行されたコードは、まったく同じエラーをスローしていました。

私のbinフォルダには、削除した古いNinject.*パッケージへの参照があったようです。これらのファイルを削除すると、私のプロジェクトは期待どおりに動作しました。

6
Ben Bailey

私の場合、Owin Selfhostコンテキストでは問題なく機能していましたが、IISでホストされている場合は機能していませんでした。私の解決策は、Ninject自体を除くすべてのNinject関連アセンブリをnugetパッケージから削除することでした。

次に、独自のDependencyResolverクラスを作成しました。コメントに改善点を残してください。

public class NinjectDepsolver : IDependencyResolver
{
    private IKernel _kernel;

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

    public void Dispose()
    {
        _kernel = null;
    }

    public object GetService(Type serviceType) => _kernel.TryGet(serviceType);

    public IEnumerable<object> GetServices(Type serviceType) => _kernel.GetAll(serviceType).ToArray();

    public IDependencyScope BeginScope() => new DepScope(this);

    class DepScope : IDependencyScope
    {
        private NinjectDepsolver _depsolver;

        public DepScope(NinjectDepsolver depsolver)
        {
            _depsolver = depsolver;
        }

        public void Dispose()
        {
            _depsolver = null;
        }

        public object GetService(Type serviceType) => _depsolver.GetService(serviceType);

        public IEnumerable<object> GetServices(Type serviceType) => _depsolver.GetServices(serviceType);
    }
}

次に、Owin Configurationメソッドで:

var kernel = new StandardKernel();
kernel.Load(<your module classes>);
var httpConfig = new HttpConfiguration();
var httpConfig.DependencyResolver = new NinjectDepsolver(kernel);
var httpConfig.MapHttpAttributeRoutes();

app.UseWebApi(httpConfig);
2

循環依存関係は、クラス「NinjectDefaultModelValidatorProvider」と「DefaultModelValidatorProviders」の間にあります。以下のように、スタートアップに「DefaultModelValidatorProviders」のバインディングを追加するだけです。

 _ kernel.Bind <DefaultModelValidatorProviders>()。ToConstant(new DefaultModelValidatorProviders(config.Services.GetServices(typeof(ModelValidatorProvider)))。Cast <ModelValidatorProvider>())); 
2
Arindam

これは私のために働いたものです。

uninstall-package Ninject.Web.WebApi.WebHost

上記のコマンドは、バージョン 'Ninject.Web.WebApi.WebHost 3.2.4.0'をアンインストールし、エラーはなくなりました!!

再確認してください。コマンドを使用して同じパッケージをインストールしました

install-package Ninject.Web.WebApi.WebHost

コマンドはパッケージ 'Ninject.Web.WebApi.WebHost 3.2.4.0'をインストールし、エラーが再表示されました。

1
VivekDev
var _surveyBusiness = _kernel.Get<ISurveyBusiness>();
_surveyBusiness.SomeFunc(user.CompanyId, user.UserId);

これも機能しています。

0
Bhanu Bhanot

Global.asaxStandardKernelが初期化されていた場所)に次の行を追加して、これを修正しました:

kernel.Bind<DefaultModelValidatorProviders>().ToConstant(new DefaultModelValidatorProviders(GlobalConfiguration.Configuration.Services.GetModelValidatorProviders()));
0
Owen Pauling