Czuję się swobodnie dzięki wstrzykiwaniu zależności za pomocą NInject w MVC3. Pracując w aplikacji MVC3, stworzyłem niestandardową fabrykę tworzenia kontrolerów za pomocą NInject, więc każdy utworzony kontroler będzie miał wstrzykiwane w nim zależności za pośrednictwem tej fabryki kontrolerów.
Teraz zaczynam opracowywać aplikację dla systemu Windows, chcę korzystać z wstrzykiwania zależności w całej aplikacji. tzn. Każdy obiekt musi zostać utworzony za pomocą NInject, aby ułatwić Testowanie Jednostek. Proszę, poprowadź mnie, aby upewnić się, że każdy utworzony obiekt musi być obsługiwany tylko przez NInject Factory.
Na przykład, jeśli w dowolnym oknie formularza na Button_Click
zdarzenie piszę:
TestClass testClass = new TestClass()
i TestClass
ma jakąkolwiek zależność, powiedzmy, ITest
wtedy to musi zostać automatycznie rozwiązane. Wiem, że mogę użyć:
Ikernel kernel = new StandardKenel()
//AddBinding()
TestClass testClass = kenel.get<TestClass>();
Ale uważam, że to nużące robić to za każdym razem, gdy chcę stworzyć obiekt. Zmusza także programistę do stworzenia obiektu w określony sposób. Czy można to poprawić?
Czy mogę mieć centralne repozytorium do tworzenia obiektów, a następnie każde stworzenie obiektu będzie automatycznie korzystać z tego repozytorium?
źródło
Odpowiedzi:
W przypadku aplikacji klienckich często najlepiej jest dostosować wzorzec, taki jak MVP (lub MVVM) i użyć powiązania danych z formularza do bazowego ViewModel lub Presenter.
W przypadku ViewModels można wstrzyknąć wymagane zależności za pomocą standardowego wstrzykiwania konstruktora.
W aplikacji Root kompozycji można połączyć cały wykres obiektów dla aplikacji. Nie musisz do tego używać kontenera DI (takiego jak Ninject), ale możesz.
źródło
Aplikacje Windows Forms zazwyczaj mają punkt wejścia, który wygląda następująco:
Jeśli ustawisz ten punkt w kodzie jako główny komponent , możesz znacznie zmniejszyć liczbę miejsc, w których masz kod jawnie wywołujący Ninject tak, jakby był Lokalizatorem usług.
Od tego momentu wstrzykujesz wszystkie swoje zależności za pomocą wstrzykiwania konstruktora.
Jeśli twoja „zależność” jest czymś, czego potrzebujesz, aby móc tworzyć wiele razy, to tak naprawdę potrzebujesz fabryki:
Możesz zaimplementować interfejs IFactory w ten sposób, aby uniknąć konieczności tworzenia mnóstwa jednorazowych implementacji:
źródło
InjectionFactory<T>
zaimplementowane, dostarczony kod powinien działać dobrze. Czy jest coś szczególnego, z czym masz problemy?Type
, ale która zagwarantuje, że uwodnione obiekty dla tejType
implementacji lub rozszerzenia danego typu ogólnego. Nic specjalnego.Zawsze piszę opakowanie adaptera dla dowolnego kontenera IoC, który wygląda następująco:
Konkretnie dla Ninject konkretna klasa adaptera wygląda następująco:
Głównym powodem tego jest wyodrębnienie frameworka IoC, dzięki czemu mogę go zastąpić w dowolnym momencie - biorąc pod uwagę, że różnica między frameworkami jest zasadniczo w konfiguracji, a nie w użyciu.
Ale jako bonus, rzeczy stają się o wiele łatwiejsze w korzystaniu z frameworka IoC wewnątrz innych frameworków, które nie obsługują go od razu. Na przykład w przypadku WinForms są to dwa kroki:
W metodzie Main po prostu utwórz instancję kontenera, zanim zrobisz cokolwiek innego.
A potem mają podstawową Formę, z której wywodzą się inne formy, która sama wywołuje Inject.
To mówi heurystyce automatycznego okablowania, aby spróbowała rekurencyjnie wstrzyknąć wszystkie właściwości w formie zgodnej z regułami ustawionymi w modułach.
źródło
Dobre wykorzystanie wstrzykiwania zależności zwykle polega na oddzieleniu kodu tworzącego obiekty i rzeczywistej logiki biznesowej. Innymi słowy, nie chciałbym, aby mój zespół często używał
new
i tworzył instancję klasy w ten sposób. Po zakończeniu nie ma możliwości łatwej zamiany utworzonego typu na inny, ponieważ określono już konkretny typ.Istnieją więc dwa sposoby rozwiązania tego problemu:
TestClass
do formularza Windows, aby miał już instancję, gdy jej potrzebuje. Kiedy Ninject tworzy twoją formę, automatycznie tworzy zależność.IKernel
do formularza Windows, a następnie użyć go do utworzenia wystąpieniaTestClass
. W zależności od stylu istnieją również inne sposoby osiągnięcia tego celu (wstrzyknięcie klasy fabrycznej, delegata fabryki itp.).W ten sposób można łatwo zamienić zarówno konkretny typ TestClass, jak i zmodyfikować faktyczną budowę klasy testowej, bez modyfikowania kodu używającego klasy testowej.
źródło
Nie używałem Ninject, ale standardowy sposób tworzenia rzeczy kiedy używasz IoC jest to zrobić poprzez A
Func<T>
gdzieT
jest typ obiektu, który chcesz utworzyć. Więc jeśli obiektT1
musi tworzyć obiekty typu,T2
to konstruktorT1
musi mieć parametr typu,Func<T1>
który jest następnie przechowywany jako pole / właściwośćT2
. Teraz, gdy chcemy utworzyć obiekty typuT2
wT1
wywołaniuFunc
.To całkowicie oddziela cię od twojego środowiska IoC i jest właściwym sposobem na kodowanie w myśleniu IoC.
Wadą tego jest to, że może być denerwujące, gdy musisz ręcznie połączyć
Func
s lub przykład, gdy twój twórca wymaga jakiegoś parametru, więc IoC nie może automatycznie uruchomićFunc
dla ciebie.http://code.google.com/p/autofac/wiki/RelationshipTypes
źródło