Staram się polepszyć z IoC, DI i OOD dla lepszej testowalności i luźniejszego sprzężenia.OOD przy użyciu kontenerów IoC - jak konstruować obiekty zależne?
Kiedy więc zaprojektować zajęcia z wykorzystaniem ciężkiego IoC oraz DI możemy endup z klas z wieloma zależnościami np
class Processor
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
//approach 1
public Processor(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
//approach 2
public Processor(IContainer container)
{
m_Service1 = container.Resolve<IService1>();
m_Service2 = container.Resolve<IService2>();
m_Service3 = container.Resolve<IService3>();
}
//approach 3
public delegate Processor Factory();
}
Im myślenia, co powinno być zwykłe podejście tutaj. Możemy zostawić konstruktora z 3 parametrów, ale jeśli mamy aplikację za pomocą autofac (na przykład) najprawdopodobniej budowy będzie rzadko być wykorzystywane do innych celów niż rozdzielając typy od jakiegoś przykład pojemnika jak
Processor proc = new Processor(
container.Resolve<IService1>(),
container.Resolve<IService2>(),
container.Resolve<IService3>());
tak myślę może podejście 2 jest lepsze, gdy zależy nam na wielu typach z kontenera. W każdym razie będziemy musieli dodać gdzieś odniesienie do autofac, więc czy nie ma powodów, żeby tego nie robić?
Autofac zapewnia także metoda fabryki delegat podejście
http://code.google.com/p/autofac/wiki/DelegateFactories
var processorFactory = container.Resolve<Processor.Factory>();
Processor processor = processorFactory.Invoke();
Więc mamy również zbliżyć 3 - nie będziemy używać konstruktorów do stworzenia naszych wystąpień klasy, zamiast będziemy nazywając rozwiązany delegata z pojemnikiem i rozwiąże dla nas zależności.
Od czasu, gdy jestem całkiem nowy w IoC, trudno powiedzieć, kiedy powinniśmy użyć 1,2,3. Mają zalety i wady.
Ogólnie uważam, że jeśli klasa ma 1 zależność, prawdopodobnie zawsze możemy zastosować podejście 1 .. poza tym, że nie jestem pewien, co wybrać i kiedy.
UPDATE czytałem o lokalizatora usług anty wzór ale Ive wymyślić 4 (lub prawdziwego 3 podejścia)
jej pobliżu ServiceLocator wyjątkiem jej nie mijamy obiekt, który wygląda tak
public class ServiceLocatorObject
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
public IService1 Service1 {get {return m_Service1;}}
public IService2 Service2 {get {return m_Service2;}}
public IService3 Service3 {get {return m_Service3;}}
public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
}
A teraz tworzymy
//approach 4
public Processor(ServiceLocatorObject servicesToUse)
{
m_Services = servicesToUse;
}
teraz mamy naszą klasę oddzielone od implementacji usługowym d jego jasne, jakie rzeczywiste zależności potrzebuje (jeśli założymy, że wszystkie usługi dostępne na przekażonym obiekcie są wymagane), ponieważ nie przekazujemy kontenera, który może zawierać 100 implementacji. Obiekt ten może być nawet ponownie wykorzystany, jeśli ta 3 kombinacja usług może być wymagana w innej klasie w naszej aplikacji. Używamy więc wzorca konstruktora DI nie ServiceLocator. Interfejs jest przejrzysty i nie jest przeładowany zależnościami, nowa klasa może być dobrym kandydatem do ponownego wykorzystania.
Co byś powiedział na ten temat?
link jest ładny, książka wygląda dokładnie tak, jak potrzebuję. Co sądzisz o trzecim podejściu? –
+1 Zobacz moją odpowiedź na dalsze komentarze. –
Używam trzeciego podejścia na całym moim kodzie ... kiedy muszę wstrzyknąć środek do tworzenia wielu wystąpień typu w czasie. Używam Windsor ... więc używam delegowanych fabryk i wstrzykuję Func kiedy wiem, że mój Procesor będzie musiał stworzyć wiele IService1s z czasem ... –
Jeff