Wie binde ich mit der Ninject Conventions Extension?
-
23-12-2019 - |
Frage
Ich binde den folgenden Code gerne mit der automatischen Ninject-Bindung.Ist es möglich, innerhalb eines einzigen Projekts sowohl die manuelle als auch die automatische Bindung zu verwenden?Nehmen wir die folgende manuelle Bindung, die ich mit der automatischen Bindung erreichen möchte.Bitte sagen Sie mir, wie ich das erreichen kann.
kernel.Bind<TestContext>().ToSelf().InRequestScope();
kernel.Bind<IUnitOfWork<TestContext>>().To<UnitOfWork<TestContext>>();
Im Folgenden werden alle von der Basisschnittstelle geerbten Schnittstellen aufgeführt: IRepository< Modell >
3 . kernel.Bind<IUserRepository>().To<UserRepository>();
4 . kernel.Bind<IAccountRepository>().To<AccountRepository>();
5 . kernel.Bind<IMessageRepository>().To<MessageRepository>().WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
Zusätzlich
Muss ich schreiben? .Exclude<MessageRepository>()
für mehrere Klassen Wenn ich es tun muss, z
.Exclude<ARepository>()
.Exclude<BRepository>()
.Exclude<CRepository>()
?
und ist für 1 und 2 eine separate manuelle Bindung erforderlich?oder 1 kann mit erfolgen BindToSelf()' and
.Configure(b => b.InRequestScope())` ?
Lösung
Ja, es ist möglich, Konventionsbindung und Einzelbindung im selben Projekt zu verwenden, sogar im selben Modul.
IBindingRoot.Bind(x => x
.FromThisAssembly()
.IncludingNonePublicTypes()
.SelectAllClasses()
.InheritedFrom(typeof(IRepository<>))
.BindDefaultInterface()
.Configure(y => y.InRequestScope()));
Sie können jedoch kein Konstruktorargument an eine bestimmte Klasse übergeben.Daher schlage ich vor, das Konstruktorargument durch eine Schnittstelle zu ersetzen, die den Zugriff auf die Konfiguration umschließt (das ist jedenfalls ein schönes Design).
Alternativ können Sie auch Folgendes tun:
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();
-> Du kannst eins machen .Exclude<TRepository>()
für jedes Repository, bei dem die Konventionsbindung nicht ausreicht.Für jede ausgeschlossene Bindung müssen Sie selbst eine angeben.Wie oben:Bedingte Bindung für alle implementierenden Klassen IRepository<>
außer Klasse MessageRepository
, das eine eigene Bindung erhält.
Schauen Sie sich auch das hier an:https://github.com/ninject/ninject.extensions.conventions/wiki/Projecting-Services-to-Bind
Nachtrag:Beachten Sie, dass Sie mehrere herkömmliche Bindungen angeben können, zum Beispiel:
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()));
Ist völlig ok.
Andere Tipps
Die vorherige Lösung funktioniert, wenn Sie nur wenige Ausnahmen haben.Wenn es mehr davon gibt, ergibt sich eine Menge Konventionen, die keinen Sinn ergeben.
Verwenden Sie die IBindingRoot.Rebind-Methode, um Bindungen zu überschreiben, die sich mit der Bindung überschneiden, die bereits von der Konvention abgedeckt wird.
IBindingRoot.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.BindAllInterface());
IBindingRoot.Rebind<IMessageRepository>().To<MessageRepository>)
.WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
.InRequestScope();