2009-10-30 19 views
6

Aby rozpocząć, używam programu Ninject 1.5. Mam dwa projekty: projekt internetowy i bibliotekę klasy. Moja konfiguracja DI znajduje się w projekcie WWW. W moim klasy biblioteki Mam następującą definicją:Ninject: Jak mogę wstrzyknąć do biblioteki klas?

public interface ICacheService<T> 
    { 
      string Identifier { get; } 
      T Get(); 
      void Set(T objectToCache, TimeSpan timeSpan); 
      bool Exists(); 
    } 

A potem beton klasy o nazwie CategoryCacheService.

W moim projekcie internetowej wiążę dwa:

Bind(typeof(ICacheService<List<Category>>)).To(typeof(CategoryCacheService)).Using<SingletonBehavior>(); 

w mojej klasie biblioteki Mam metody rozszerzenie dla klasy HtmlHelper, na przykład:

public static class Category 
{ 
    [Inject] 
    public static ICacheService<List<Category>> Categories { get; set; } 

    public static string RenderCategories(this HtmlHelper htmlHelper) 
    { 
    var c = Categories.Get(); 

    return string.Join(", ", c.Select(s => s.Name).ToArray()); 
    } 
} 

Powiedziano mi, że Ciebie nie mogę wstrzyknąć do właściwości statycznych, zamiast tego powinienem użyć Kernel.Get <>() - Jednak ... Ponieważ powyższy kod znajduje się w bibliotece klas, nie mam dostępu do jądra. Jak mogę zdobyć jądro od tego punktu, czy jest lepszy sposób na zrobienie tego?

Odpowiedz

8

Dobre pytanie.

Połówek pomysłu użycia DI polega na usunięciu problemu/dostrojenia zachowania instancji z kodu pod zastrzykiem. Dlatego bardziej sensownym może być zmiana klasy Category, aby nie była już static, zadeklarowanie jej zależności w ctor i pozostawienie kodu klienta razem.

Odnośnie sposobu dostępu do niego, jeśli jesteś naprawdę pewien, że jest to dobry pomysł ... Generalnie pomysł w twoim przypadku polegałby na utworzeniu CacheServiceResolver i zarejestrowaniu go [w twoim projekcie internetowym]. Następnie przekazuje go instancji Kernel podczas konstruowania. W ten sposób twoja biblioteka DLL jest tylko związana z interfejsem twojego CacheServiceResolver.

Innym często stosowanym podejściem jest posiadanie w ostatnim czasie ośrodka "Service Locator" ostatniej instancji, który eksponuje "GlobalGet". Ale na ogół jest to Zły pomysł i powinien być używany tylko do tymczasowego nagrywania taśmą.

Inną rzeczą, na którą warto zwrócić uwagę jest Common Service Locator, który pozwoli na ustawienie neutralnego kontenera w bibliotece, ale poza EL, nie znajdziesz dużego zastosowania jako you shouldnt really show your container.

Inną opcją jest do żądania metodę Func<T> fabryki i Bind że do lambda, która rozwiązuje go, wydobywania tego odnośnika z kodu.

EDIT: W Ninject 2, nie ma potrzeby, aby wyraźnie przekazać w Kernel przypadkach jak mówiłem - można po prostu poprosić o IKernel w swojej ctor i dostaniesz to, niezależnie od tego, czy wniosek rozdzielczości expclicitly przechodzi jedno w.

EDYCJA 2: Naprawdę niezadowolony z mojej odpowiedzi, próbowałem uczynić ją bardziej ogólną bez zbytniego jej rzeźbienia.Podsumowanie jest to pożądane opcje są na ogół w następujących w kolejności:

  1. żadnych artefaktów kontenerów, pozostaw zszywanie do klienta
  2. dostarczenie pojemnika neutralny punkt wewnętrzny, dopasowany specjalnie coś osiągnąć w kontekście biblioteki przy użyciu terminologia w wszechobecnego Język biblioteki w domenie zamiast zneutralizowanych abstrakcyjnych pojęć kontenerowych
  3. zapewnić integrację pojemnik neutralne podejście a la Common Service Locator
  4. tylko wtedy rozważyć osoby, która chciałaby
    • znać swój pojemnik
    • zrozumieć Twój pojemnik
+0

Ruben, CacheServiceResolver wydaje mi się właściwym pomysłem, ponieważ Mogę ponownie wykorzystać ten wzorzec w przyszłości. Czy masz jakieś przykłady dotyczące konfigurowania programu tłumaczącego? – DennyFerra

+0

Niestety nie mam jednego do ręki. Ogólną ideą byłoby to, że gdziekolwiek tworzysz swój nowy StandardKernel, przechowujesz odniesienie do niego. Następnie masz coś tak prostego, jak 'void RegisterCacheServiceResolver (jądro jądra) {Bind (). ToConstant (nowy CacheServiceResolver (jądro));}' na jednym z modułów, do którego przekazujesz jądro. Można też utworzyć jądro, a następnie przekazać je konstruktorowi dowolnego modułu, który go potrzebuje, po czym dodaje się moduł [w przeciwieństwie do przekazywania wszystkich w konstruktorze jądra, jak zwykle]. –

4

W projekcie internetowej uruchom następujące polecenie z konsoli Package Manager.

Install-Package Ninject.MVC3 

Powinieneś skończyć z modułem NinjectWebCommon w folderze App_Start.

kierunku dna można dodać zależności, jak poniżej:

private static void RegisterServices(IKernel kernel) 
{ 
kernel.Bind<IPeopleRepository>().To<PeopleRepository>(); 
} 

Od projektu biblioteki klasy uruchom następujące polecenie:

Install-Package Ninject 

ten sposób, aby wprowadzić usługę z repozytorium z biblioteka klas:

public class PeopleService : IPeopleService 
{ 
private readonly IPeopleRepository _peopleRepository; 

[Inject] 
public PeopleService(IPeopleRepository peopleRepository) 
{ 
    this._peopleRepository = peopleRepository; 
} 
} 
Powiązane problemy