2008-11-10 16 views
10

Ogólnie rzecz biorąc, chciałbym, aby aplikacja zupełnie nie znała kontenera IoC. Jednak natknąłem się na problemy, w których potrzebowałem uzyskać do niego dostęp. Aby usunąć ból, używam podstawowego Singletona. Zanim wybierzesz się na wzgórza lub wyciągniesz strzelbę, pozwól mi przejrzeć moje rozwiązanie. Zasadniczo singleton IoC absolutnie nic nie robi, po prostu przenosi się do wewnętrznego interfejsu, który musi zostać przekazany. Odkryłem, że to sprawia, że ​​praca z Singletonem jest mniej bolesna.Abstrahowanie do kontenera IoC za Singleton - Czy to źle?

Poniżej jest owinięcie IoC:

public static class IoC 
    { 
     private static IDependencyResolver inner; 

     public static void InitWith(IDependencyResolver container) 
     { 
      inner = container; 
     } 

     /// <exception cref="InvalidOperationException">Container has not been initialized. Please supply an instance if IWindsorContainer.</exception> 
     public static T Resolve<T>() 
     { 
      if (inner == null) 
       throw new InvalidOperationException("Container has not been initialized. Please supply an instance if IWindsorContainer."); 

      return inner.Resolve<T>(); 
     } 

     public static T[] ResolveAll<T>() 
     { 
      return inner.ResolveAll<T>(); 
     } 
    } 

IDependencyResolver:

public interface IDependencyResolver 
    { 
     T Resolve<T>(); 
     T[] ResolveAll<T>(); 
    } 

miałem wielki sukces do tej pory kilka razy używałem go (może raz na kilka projektów, Naprawdę wolę nie używać tego w ogóle), ponieważ mogę wstrzyknąć wszystko, czego chcę: zamek, kikut, podróbki itp.

Czy to śliska droga? Czy napotkam potencjalne problemy w dół drogi?

Odpowiedz

4

Widziałem, że nawet Ayende wdraża ten wzór w kodzie Rhino Commons, ale odradzam używanie go w miarę możliwości. Jest powód, dla którego Castle Windsor nie ma tego domyślnego kodu. StructureMap to robi, ale Jeremy Miller od niego odchodzi. Najlepiej byłoby, gdyby sam pojemnik był tak samo podejrzany, jak każda zmienna globalna.

Alternatywnie można jednak skonfigurować kontener w celu rozpoznania IDependencyResolver jako odniesienia do kontenera. To może wydawać się szalone, ale jest znacznie bardziej elastyczne. Po prostu zapamiętaj regułę, że obiekt powinien wywoływać "nowy" lub wykonywać przetwarzanie, ale nie oba. W przypadku "call new" zamień na "resolve a reference".

3

To nie jest klasa singletona. To statyczna klasa ze statycznymi członkami. I tak, wydaje się to dobrym podejściem.

Myślę, że JP Boodhoo ma nawet nazwę tego wzoru. The Static Gateway pattern.

2

Uwaga: w Microsoft Patterns and Practices stworzono wspólny lokalizator usług (http://www.codeplex.com/CommonServiceLocator), który większość dużych kontenerów IoC będzie wdrażać w niedalekiej przyszłości. Możesz zacząć używać go zamiast swojego IDependencyResolver.

BTW: jest to popularny sposób rozwiązania problemu i działa całkiem dobrze.

1

Wszystko zależy od sposobu użycia. Używanie takiego kontenera nazywa się wzorcem usługi serwisowej. Są przypadki, w których nie jest to dobre dopasowanie i przypadki, w których mają one zastosowanie.

Jeśli google "wzorzec lokalizatora usług" zobaczysz wiele postów na blogu, które mówią, że jest to wzorzec, którego nie ma. Wzór został po prostu nadużywany (/ maltretowany).

W przypadku typowych aplikacji biznesowych nie należy używać SL podczas ukrywania zależności. Masz również inny problem: Nie możesz zarządzać stanem/czasem życia, jeśli używasz kontenera głównego (zamiast jednego z jego okresów życia).

Lokalizator usług jest dobrym rozwiązaniem, jeśli chodzi o infrastrukturę. Na przykład ASP.NET MVC używa Service Locator, aby móc rozwiązać wszystkie zależności dla każdego kontrolera.

Powiązane problemy