Ninjectシングルトンをセットアップする方法
MyFacade
でパラメーターを挿入したクラス(Ninject
)があります。
_class MyFacade
{
IDemoInterface demo;
public MyFacade(IDemoInterface demo)
{
this.demo = demo;
}
public void MyMethod()
{
Console.WriteLine(demo.GetInfo());
}
}
_
もちろん、パラメータの適切な実装を挿入するには、Ninject
を設定する必要があります(IDemoInterface
)
kernel.Get<MyFacade>();
を実行することで、何も設定せずにMyFacade
オブジェクトをインスタンス化できることはわかっています。現在、私のファサードにはインターフェイスがありません(これが私の唯一の実装であるため、標準の提案用にインターフェイスを追加する可能性があります)
このファサードをシングルントンにしたい場合は、2つの方法を知っています。空のコンストラクターを作成し、このkernel.Get<IDemoInterface>();
を実行するか、次のようにNinjectを設定してパラメーターを渡します。kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
2つ目はより良いアプローチに見えますが、シングルトン方式でセットアップする他の方法を知っていますか?
バインディングを設定するときは、依存関係をバインドする必要があります。コンストラクターでkernel.Get<T>()
を実行するのではなく、バインディングで依存関係を設定することをお勧めします。 IOCを使用しているので、使用しているフレームワークを活用してインジェクションを実行します。
2番目のバインディングの例では、不足しているのはIDemoInterface
でのバインディングです。バインディングは次のようになります。
//bind the dependency to the implementation.
kernel.Bind<IDemoInterface>().To<DemoInterface>();
//since you bound your dependency, ninject should now have
// all the dependencies required to instantiate your `MyFacade` object.
kernel.Bind<MyFacade>.To<MyFacade>().InSingletonScope();
コンテナがInSingletonScope()
を使用してシングルトンのライフサイクルを管理することを望まないが、それでもコンテナを注入したい場合は、2つの方法が考えられます。ニーズに合ったものを選択してください。次のISingleton
(インターフェイスに名前を付ける)の実装を検討してください。
_public class ConcreteSingleton : ISingleton
{
private static readonly Lazy<ConcreteSingleton> _instance = new Lazy<ConcreteSingleton>(() => new ConcreteSingleton());
private ConcreteSingleton() { }
public static ConcreteSingleton Instance
{
get
{
return _instance.Value;
}
}
}
_
シングルトンクラスを変更してa
GetInstance(...)
methodこのメソッド(私の推奨するアプローチ)では、シングルトンが初めて初期化されるときにのみ、毎回
kernel.Inject(instance)
を呼び出すことはありません。ConcreteSingleton
クラスに次のメソッドを追加します。_
public static ConcreteSingleton GetInstance(IKernel kernelForInjection) { if (_instance.IsValueCreated == false) { kernelForInjection.Inject(_instance.Value); } return _instance.Value; }
_そして、このバインディングを使用します。
_
kernel.Bind<ISingleton>().ToMethod(c => ConcreteSingleton.GetInstance(c.Kernel));
_パブリックコンストラクターを持たないが、ファサードを効率的に注入できるようにするという望ましい動作を実現します。
ISingleton
インスタンスが要求されるたびにインジェクションを実行します何らかの理由で
ConcreteSingleton
の変更が許可されていない場合:このアプローチでは、プロバイダーでシングルトンの作成をラップして、インスタンスが初めて作成されたときにのみ効率的にインスタンスを注入します。プロバイダー自体はシングルトンとして登録する必要があることに注意することが重要です。_
internal class ConcreteSingletonProvider : Provider<ISingleton> { public IKernel Kernel { get; set; } //Just a wrapper private readonly Lazy<ISingleton> _lazy = new Lazy<ISingleton>(() => ConcreteSingleton.Instance); public ConcreteSingletonProvider(IKernel kernel) { Kernel = kernel; } protected override ISingleton CreateInstance(IContext context) { if (_lazy.IsValueCreated == false) { Kernel.Inject(ConcreteSingleton.Instance); } return _lazy.Value; } }
_そして、バインディングは次のようになります。
_
kernel.Bind<ISingleton>().ToProvider<ConcreteSingletonProvider>(); kernel.Bind<ConcreteSingletonProvider>().ToSelf().InSingletonScope();
_この 要点 には、上記のアプローチの完全な作業サンプルがあります。
お役に立てば幸いです。