7

W tej chwili mam kilka usług, które są zdefiniowane w zestawie, który nie jest zależny od kontenera IoC (Ninject w moim przypadku). W głównym projekcie mam IRepository dla dostępu do danych zarejestrowany w kontenerze.Ogólna praktyka IoC - czy korzystanie z usług zależy od siebie nawzajem?

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>(); 

ja również usługi IAuthenticationService i IErrorLogger zarejestrowany, którego konkretna realizacja chcę użyć repozytorium dla ich logiki. Jednak nie jestem pewien, jak najlepiej to osiągnąć. Obecnie mój konstruktor zarówno konkretnych wdrożeń wziąć IRepository parametr i mijam go kiedy je zarejestrować:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>(). 
       WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository()); 

Tu wystarczy powiedzieć pojemnik chwycić IRepository instancji i przekazać je do konstruktora.

Nie miałem racji co do tego, czy mój zestaw usług jest zależny od ninja, czy nawet od wspólnego lokalizatora usług (CSL), ale nie jestem również pewny co do mojego obecnego sposobu. Szukam opinii i alternatywnych rozwiązań.

Jeśli moje inne usługi nie będą korzystać z IRepository, będę musiał utworzyć nowe konkretne implementacje tych usług dla każdego typu bazowego typu IRepository (np. Usługa uwierzytelniania dla fałszywych i rzeczywistych danych). Byłoby to dużo powtórzeń logicznych.

Odpowiedz

6

Twój zestaw usług nie powinien zależeć od Ninject, tylko na interfejsach, dla których rejestrujesz konkretne typy. Kontener IoC powinien być tylko głównym agregatem, aby wstrzykiwać zależności do twoich klas. Z kolei zestaw zawierający agregowane jądro/jądro Ninject będzie zależało od wszystkich złożeń, które zawierają konkretne typy (jak inaczej mógłby je rozwiązać?).

Ogólnie z IoC należy zastosować Hollywood principle tutaj - należy dać zależności do konkretnych instancji obiektów (przy użyciu konstruktora wtrysku jeśli w ogóle możliwe), nie pozwól instancje obiektów zapytać dla ich zależności.

Przykład używać do WithConstructorArgument() nie powinny być w ogóle potrzebne rzeczywiście, ponieważ rozdzielczość zależność działa rekurencyjnie: Zarejestrowano zarówno IRepository i IAuthenticationService z pojemnika, więc wie, jak rozwiązać oba. Ponieważ IAuthenticationService jest związany z AuthenticationService, nie trzeba określać argumentu konstruktora, ponieważ jest on typu IRepository i zostanie rozwiązany automatycznie.

Co do powtórzenia - oczywiście trzeba będzie tworzyć różne implementacje dla IRepository dla różnych typów repozytoriów zakładając chcesz różne zachowanie tych repozytoriach.

+0

Świetne informacje! Masz rację, nie musiałem w ogóle określać obiektu WithConstructorArgument. Zostały one automatycznie wstrzyknięte. Jeszcze jedno pytanie: jeśli zarejestruję 2 implementacje IRepository, każda o innej nazwie. Następnie chcę określić ten, który ma wstrzyknąć. Wiem, że istnieje NamedAttribute z Ninject, ale aby uniknąć dodawania zależności Ninject do mojego zestawu usług, nie chciałbym tego użyć. Więc ręczne określenie byłoby sposobem, aby przejść w tym przypadku? FYI, mój powód do powtórzenia nie dotyczył IRepository, ale innych klas usług. – Adam

+2

Dla Ninject można użyć 'WhenInjectedInto ()' gdzie Foo jest twoją klasą usług.Zazwyczaj rejestrujesz tylko jedną konkretną implementację swojego repozytorium - te dla fałszywych danych i testów nie powinny być rejestrowane jako część głównej aplikacji, tylko w osobnym pojemniku testowym – BrokenGlass

+0

Idealne, jeszcze raz dziękuję. – Adam

Powiązane problemy