9

WebAPIアプリケーションでninjectmvc3プラグインを使用しています。次のようなバインディングがあります。

kernel.Bind<IFoo>().To<Foo>().InSingletonScope();

Fooカーネルは、のインスタンスを1つだけ作成し、それを適切に再利用するというのが私の解釈です。のコンストラクターにブレークポイントを設定することFooで、要求ごとに1回呼び出されることがはっきりとわかり、その理由を説明できません。

私の唯一の推測は、リクエストごとに新しいカーネルが作成されているということですがCreateKernel、グローバル依存関係リゾルバーを設定するメソッドはアプリケーションの存続期間中に1回しか実行されないため、そうではないようです。

この投稿から取得したコードを使用して、ninjectをmvc 4でうまく再生できるようにしています。フレームワークが変更されたため、次の場所に割り当てる追加のラッパーを作成する必要がありましたGlobalConfiguration.Configuration.DependencyResolver

public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private readonly IKernel _kernel;
    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

私は何が間違っているのですか?

4

4 に答える 4

5

私はそれを正しく動作させることができませんでした、そして私は理由がわかりません。私の推測では、MVC4の統合は現時点では少し未成熟であることに関係しています。

別の方法として、私は以下を使用しています。

kernel.Bind<IFoo>().ToConstant(new Foo());

これはうまくいくようですが、私はあまり満足していません。

于 2012-10-12T22:11:45.383 に答える
4

前に述べたように、それはバグのように見えます。
1つのオプションは、シングルトン拡張メソッドを自分で実装することです。

public static class NinjectSingletonExtension
{
    public static CustomSingletonKernelModel<T> SingletonBind<T>(this IKernel i_KernelInstance)
    {
        return new CustomSingletonKernelModel<T>(i_KernelInstance);
    }
}

public class CustomSingletonKernelModel<T>
{
    private const string k_ConstantInjectionName = "Implementation";
    private readonly IKernel _kernel;
private static object padlock = new Object();

    private T _concreteInstance;


    public CustomSingletonKernelModel(IKernel i_KernelInstance)
    {
        this._kernel = i_KernelInstance;
    }

    public IBindingInNamedWithOrOnSyntax<T> To<TImplement>(TImplement i_Constant = null) where TImplement : class, T
    {
        _kernel.Bind<T>().To<TImplement>().Named(k_ConstantInjectionName);
        var toReturn =
            _kernel.Bind<T>().ToMethod(x =>
                                       {
                                           if (i_Constant != null)
                                           {
                                               return i_Constant;
                                           }

                                           if (_concreteInstance == null)
                       {
                       lock (padlock)
                       {
                        if (_concreteInstance == null)
                        {
                            _concreteInstance = _kernel.Get<T>(k_ConstantInjectionName);
                        }
                           }
                       }


                                           return _concreteInstance;
                                       }).When(x => true);

        return toReturn;
    }
}

そして、単に使用します:

i_Kernel.SingletonBind<T>().To<TImplement>();

むしろその後

i_Kernel.Bind<T>().To<TImplement>().InSingletonScope();


于 2014-04-03T14:18:51.917 に答える
4

確かにこのスレッドに遅れて到着しましたが、Web APIコントローラー用のOWINをホストし、Ninjectで依存関係を解決するWindowsサービスで起こったのですが、InSingletonScope()は次のことを行うまで機能しませんでした。

var kernel = new StandardKernel();
...
kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<IFoo>().ToMethod(context => context.Kernel.Get<Foo>());
...

// Controllers ask for the dependency as usual...
public class SomeController : ApiController
{
    readonly IFoo _foo;

    public SomeController(IFoo foo)
    {
        _foo = foo;
    }
...

お役に立てれば

于 2017-03-22T22:12:30.940 に答える
1

注:私はnugetを使用してninjectとninject.web.mvcをインストールしました(これもあなたが行ったと確信しています)。

残りのコードは表示できませんが、「NinjectDependencyScope」クラスにあるものは次のとおりです。(私はあなたのものが単にNinjectScopeと呼ばれていると思います、あなたのコードとのいくつかの他の命名の矛盾かもしれません)

public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot _resolver;

    internal NinjectDependencyScope(IResolutionRoot resolver)
    {
        Contract.Assert(resolver != null);

        _resolver = resolver;
    }

    #region IDependencyScope Members

    public void Dispose()
    {
        var disposable = _resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();

        _resolver = null;
    }

    public object GetService(Type serviceType)
    {
        if (_resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");
        return _resolver.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        if (_resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return _resolver.GetAll(serviceType);
    }

    #endregion
}

そして、これが私のNinjectWebCommonクラス(App_Startフォルダーにあります)です。

using System;
using System.Web;
using System.Web.Http;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Common;

[assembly: WebActivator.PreApplicationStartMethod(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Stop")]

namespace ABCD.Project.Web.App_Start
{
public static class NinjectWebCommon 
{
    private static readonly Bootstrapper Bootstrap = new Bootstrapper();

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

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

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

        RegisterServices(kernel);

        // Set Web API Resolver
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        //var modules = new INinjectModule[] { new NinjectBindingModule(), };
        //kernel.Load(modules);
        Here's where you would load your modules or define your bindings manually...
    }        
}
}
于 2012-10-08T15:15:01.563 に答える