2010-06-17 4 views
5

Próbuję zacząć od prostego zastrzyku zależności za pomocą C# i natknąłem się na problem, na który nie mogę wymyślić odpowiedzi.Wstrzyknięcie zależności C# - jak wprowadzić zastrzyk bez źródła?

Mam zajęcia, które zostały napisane przez inny dział, dla którego nie mam źródła w moim projekcie. Chciałem wstrzyknąć obiekt tego typu za pomocą konstruktora za pomocą interfejsu, ale oczywiście nie mogę zmienić implementacji zastrzyków obiektów w celu implementacji interfejsu w celu uzyskania polimorfizmu podczas rzutowania obiektu na typ interfejsu.

W każdym akademickim przykładzie, jaki kiedykolwiek widziałem w tej technice, klasy używają klas zadeklarowanych w samym projekcie. W jaki sposób chciałbym wstrzyknąć moją zależność bez źródła dostępnego w projekcie?

Mam nadzieję, że to ma sens, dzięki.

Odpowiedz

0

Jeśli nie potrzebujesz niczego zmieniać w klasie, prawie nie potrzebujesz kodu. Załóżmy, że masz klasę X w bibliotece DLL, którą chcesz wprowadzić do innej klasy Y, którą piszesz. W takim przypadku możesz utworzyć instancję X i umieścić ją jako parametr w konstruktorze Y. To będzie wyglądać mniej więcej tak:

Dodaj odwołanie do biblioteki DLL zawierającej klasę X w swoim projekcie.

Use NameSpaceOfX; 
Class Y 
{ 
    Public Y() //Default constructor 
    { 
    } 

    Public Y(X instanceOfX) 
    { 
     //Use instanceOfX here as required 
    } 
} 

W Tobie kod główny:

//Create instance of X 
X instanceOfX = new X(); 
//Inject it into Y 
Y instanceOfY = new Y(instanceOfX); 
//Use Y now. 
6

Można by stworzyć owinięcie wokół typ docelowy, tak na przykład można mieć klasę stanowią one:

public class TheirClass 
{ 
    public void DoSomething(); 
} 

Z jakimi możesz zdefiniować interfejs:

public interface ITheirClass 
{ 
    void DoSomething(); 
} 

i wdrożenie tego interfejsu w klasie Wrapper:

public class TheirClassWrapper : TheirClass, ITheirClass 
{ 

} 

Lub, jeśli klasa one przewidziane jest uszczelniona, trzeba zrobić to nieco inaczej:

public class TheirClassWrapper : ITheirClass 
{ 
    private TheirClass instance = new TheirClass(); 

    public void DoSomething() 
    { 
    instance.DoSomething(); 
    } 
} 

Następnie można wstrzyknąć tego interfejsu zamiast.

Wiem, że w MEF możemy eksportować konkretne typy i właściwie je wstrzykiwać, ale nie jestem pewien co do innych pojemników IoC.

+0

To było dokładnie to, co myślał. – Steven

+0

Wzór adaptera. Dobra decyzja. – Wix

1

Pytanie brzmi, dlaczego chcesz go wprowadzić jako interfejs? Czy to dlatego, że klasa implementuje niektóre właściwości/metody, które chcesz usunąć, aby można je było zastąpić, czy po prostu próbujesz "wymusić" na nim interfejs znacznika, ponieważ "zawsze polegamy na interfejsach, a nie konkretnych klasach" ? Jeśli jest to drugie, to jesteś na złej drodze, ponieważ prawdopodobnie i tak rzucisz to na beton natychmiast.

Zakładając, że były z nimi widzę dwie opcje:

  1. użyty zamiast dziedziczenia. To może, ale nie musi być możliwe w zależności od klasy, która została utworzona, ale możesz ją odziedziczyć i zastąpić ją nową.
  2. Utwórz interfejs samodzielnie, za pomocą wymaganych metod/właściwości i zawiń zewnętrzną klasę betonu w klasę implementującą interfejs.

Dla opcji 2, jeśli nie można dziedziczyć, jako przykład, zakładając, że tylko o jedną metodę w klasie (będziemy go nazywać Method1()) utworzyć interfejs pasujący do niego:

public interface IMyNewInterface 
{ 
    void Method1(); 
} 

Następnie utwórz implementację to, że przybiera konkretną klasę jako zależność (wtryskiwanego przez kontener jako normalny), że po prostu wywołuje konkretną klasę:

public class MyNewClass : IMyNewInterface 
{ 
    private MyConcreteClass _MyConcreteClass; 

    public void MyNewClass(MyConcreteClass concreteClass) 
    { 
     _MyConcreteClass = concreteClass; 
    } 

    public void Method1() 
    { 
     _MyConcreteClass.Method1(); 
    } 
} 
+0

Ale z tą ostatnią z dwóch opcji możliwe byłoby przetestowanie własnej klasy, która używa klasy trzeciej jako argumentu przekazanego do konstruktora. tj. byłoby możliwe wyśmiać TheirClass za pomocą ITheirClass –

+0

Obie opcje umożliwiają zastąpienie ich klasy (odkładanie na bok), podejściem do interfejsu byłoby jednak moje upodobanie. –

+0

Przepraszam, nie miałem na myśli opcji 1 i 2. Odnosiłem się do cytatu ".. zawsze polegam ...". Być może źle odczytałem. Może miałeś na myśli, że nie powinno się tego robić tylko ze względu na bycie skończonym. Ale dobre praktyki oznaczają, że ułatwimy przyszłe zmiany lub konserwację. Jeśli klasa została wstrzyknięta, łatwiej byłoby wstrzyknąć ją np. Do pomiaru wydajności? –