Nie jest dla mnie jasne, w jaki sposób mogę zaprojektować, więc zachowuję odniesienie do kontenera DI w katalogu głównym kompozycji dla aplikacji Silverlight + MVVM.Utrzymywanie użycia kontenera DI w głównym składzie w Silverlight i MVVM
Mam następujący prosty scenariusz użycia: istnieje widok główny (być może lista elementów) i akcja otwierająca widok edycji dla pojedynczego elementu. Główny widok musi więc tworzyć i pokazywać widok edycji, gdy użytkownik wykona akcję (np. Kliknie jakiś przycisk).
Do tego mam następujący kod:
public interface IView
{
IViewModel ViewModel {get; set;}
}
Następnie dla każdego widoku, że muszę być w stanie stworzyć mam Abstract Factory, podobnie jak
public interface ISomeViewFactory
{
IView CreateView();
}
Fabryka ta jest następnie zadeklarowano zależność modelu widoku "macierzystego", tak jak to:
public class SomeParentViewModel
{
public SomeParentViewModel(ISomeViewFactory viewFactory)
{
// store it
}
private void OnSomeUserAction()
{
IView view = viewFactory.CreateView();
dialogService.ShowDialog(view);
}
}
Wszystko jest dobrze, dopóki nie pojawi się tu DI -kontener w zasięgu wzroku :). Teraz przychodzi implementacja ISomeViewFactory:
public class SomeViewFactory : ISomeViewFactory
{
public IView CreateView()
{
IView view = new SomeView();
view.ViewModel = ????
}
}
"????" część jest moim problemem, ponieważ model widoku dla widoku musi zostać rozwiązany z kontenera DI, aby uzyskać wstrzyknięte jego zależności. To, czego nie wiem, to jak mogę to zrobić bez zależności od kontenera DI w dowolnym miejscu z wyjątkiem katalogu głównego kompozycji.
Możliwym rozwiązaniem byłoby mieć albo zależność od modelu widoku, który zostaje wstrzyknięty do fabryki, tak jak poniżej:
public class SomeViewFactory : ISomeViewFactory
{
public SomeViewFactory(ISomeViewModel viewModel)
{
// store it
}
public IView CreateView()
{
IView view = new SomeView();
view.ViewModel = viewModel;
}
}
Chociaż to działa, to ma problem, ponieważ wykres cały obiekt jest okablowane "statycznie" (tzn. model widoku "rodzica" otrzyma instancję SomeViewFactory, która otrzyma instancję SomeViewModel i będą one działać tak długo, jak długo będzie istniał model widoku macierzystego), implementacja modelu widoku wstrzykniętego jest stanowy i jeśli użytkownik otwiera widok podrzędny dwa razy, drugi raz model widoku będzie tą samą instancją i będzie miał stan sprzed. Sądzę, że mógłbym obejść to z metodą "Initialize" lub czymś podobnym, ale nie pachnie całkiem poprawnie.
Innym rozwiązaniem mogłoby być owinąć DI-kontener i mieć fabryki zależy na opakowaniu, ale ja nadal być DI-kontener „w przebraniu” tam :)
PS: moje obecne rozwiązanie jest że fabryki wiedzą o kontenerze DI, i tylko one i główny katalog mają tę zależność.
Wielkie dzięki. Chociaż twoja implementacja jest krystalicznie czysta, to, co faktycznie zrobiłem, było właśnie zadeklarowanie zależności dla modelu widoku w moich fabrykach, ponieważ są one naprawdę bardzo proste i czułem, że posiadanie czegoś takiego, jak populator, jest dla mnie przesadzone. Mimo to, z punktu widzenia SOLID, a szczególnie, gdy sprawy komplikują się, oddzielając odpowiedzialność, tak jak to robiłeś, ma to wiele sensu. Świetne rzeczy :) –
Cieszę się, że pomogłem :) –