Ninject Conventions Extension を使用してバインドするにはどうすればよいですか?
-
23-12-2019 - |
質問
私は以下のコードを Ninject 自動バインディングでバインドするのが好きです。単一プロジェクト内で手動バインディングと自動バインディングの両方を使用することはできますか?以下の手動バインディングを考えてみましょう。自動バインディングで実現したいと思います。これを達成する方法を教えてください。
kernel.Bind<TestContext>().ToSelf().InRequestScope();
kernel.Bind<IUnitOfWork<TestContext>>().To<UnitOfWork<TestContext>>();
基本インターフェイスから継承されたすべてのインターフェイスは次のとおりです。 IRepository< モデル >
3 . kernel.Bind<IUserRepository>().To<UserRepository>();
4 . kernel.Bind<IAccountRepository>().To<AccountRepository>();
5 . kernel.Bind<IMessageRepository>().To<MessageRepository>().WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
追加
書く必要がありますか .Exclude<MessageRepository>()
複数のクラスの場合など、それを行う必要がある場合
.Exclude<ARepository>()
.Exclude<BRepository>()
.Exclude<CRepository>()
?
1 と 2 については、個別の手動バインディングが必要ですか?または 1 を使用して実行できます BindToSelf()' and
.Configure(b => b.InRequestScope())` ?
解決
はい、同じモジュール内であっても、同じプロジェクト内で規約バインディングと単一バインディングを使用することができます。
IBindingRoot.Bind(x => x
.FromThisAssembly()
.IncludingNonePublicTypes()
.SelectAllClasses()
.InheritedFrom(typeof(IRepository<>))
.BindDefaultInterface()
.Configure(y => y.InRequestScope()));
ただし、コンストラクターの引数を特定のクラスに渡すことはできません。したがって、コンストラクターの引数を、構成へのアクセスをラップするインターフェイスに置き換えることをお勧めします(それはとにかく素晴らしい設計です)。
あるいは、次のようにすることもできます。
IBindingRoot.Bind(x => x
.FromThisAssembly()
.IncludingNonePublicTypes()
.SelectAllClasses()
.InheritedFrom(typeof(IRepository<>))
.Exclude<MessageRepository>()
.BindDefaultInterface()
.Configure(y => y.InRequestScope()));
IBindingRoot.Bind<IMessageRepository>().To<MessageRepository>)
.WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
.InRequestScope();
--> 1 つ実行できます .Exclude<TRepository>()
規約バインディングが十分ではないすべてのリポジトリに対して。除外されたバインディングごとに、自分でバインディングを指定する必要があります。上記のように:実装するすべてのクラスの条件バインディング IRepository<>
を除外する クラス MessageRepository
, 、独自のバインディングを取得します。
こちらもご覧ください:https://github.com/ninject/ninject.extensions.conventions/wiki/Projecting-Services-to-Bind
補遺:複数の従来のバインディングを指定できることに注意してください。たとえば、次のようになります。
IBindingRoot.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IFoo))
.BindDefaultInterface()
.Configure(y => y.InRequestScope()));
IBindingRoot.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IBar))
.BindToSelf()
.Configure(y => y.InRequestScope()));
全然大丈夫ですよ。
他のヒント
前の解決策は、例外の数が少ない場合に機能します。それらの数が増えると、意味をなさない多くの規約ができてしまいます。
IBindingRoot.Rebind メソッドを使用して、すでに規約でカバーされているバインディングと重複するバインディングをオーバーライドします。
IBindingRoot.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.BindAllInterface());
IBindingRoot.Rebind<IMessageRepository>().To<MessageRepository>)
.WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
.InRequestScope();