Jak rozwiązać problem zależności?

0

Hej, buduję sobie aplikację desktopową w C# WPF. Bazując na tej odpowiedzi stworzyłem solucję o strukturze jak poniżej:

drzewo

Wydaje mi się trochę że przekombinowałem, bo teraz próbując otworzyć dialog z modelu widoku lub serwisów nie mam dostępu do widoków :/ zakładając, że:

  • warstwa G_Hoover.Contracts wie tylko o:
    • G_Hoover.Models
  • warstwa G_Hoover.Desktop wie o:
    • G_Hoover.Contracts
    • G_Hoover.Models

Jak Wy byście ogarnęli komunikację między widokami i modelami widoków? Chciałem też otwierać dialogi z Services.Controls, a nie z VM, dlatego też zależało mi żeby Services wiedziały o ViewModels, co bym mógł przekazać do okna dialogu jego ownera (czyli VM) w ten sposób:

bool? success = _dialogService.ShowOpenFileDialog(browserViewModel, settings);

Dlatego też przeniosłem ViewModels do G_Hoover.Contracts. Czy po prostu otwierać dialogi z VM? Dla wygody otwierania okien dialogowych korzystam z MvvmDialogs. Przykład z modelu widoku:

SearchPhrase = ShowDialog(viewModel => _dialogService.ShowDialog<PhraseView>(this, viewModel));
0

Wstępnie częściowo mogę odpowiedzieć na swoje pytanie. MvvmDialogs otwiera modalne dialogi na 2 sposoby:

SearchPhrase = ShowDialog(viewModel => _dialogService.ShowDialog<PhraseView>(this, viewModel));

oraz

SearchPhrase = ShowDialog(viewModel => _dialogService.ShowDialog(this, viewModel));

Gdzie w drugim przypadku szuka widoku po konwencji nazwy VM. W obu przypadkach chyba jest to zaprzeczenie wzorca MVVM, więc framework do śmieci. Teraz chyba pozostaje mi znalezienie sposobu na otwieranie dialogów przy wysłaniu samego VM... (?) Znalazłem przykład w którym się rejestruje w serwisie pary VM/M w słowniku, może wypali, spróbuję to ogarnąć:


public void Register<TViewModel, TView>() where TViewModel : IDialogRequestClose
                                                  where TView : IDialog

Ale jak byście mieli ciekawsze pomysły, to piszcie śmiało ;p

3

Disclaimer: nie znam się na WPF

Ta architektura zaproponowana przez somekinda jest dobra do aplikacji webowych i opiera się na pewnym kompromisie. W webie ViewModele są jedynie pojemnikami na dane niemającymi żadnej logiki (ewentualnie atrybuty dotyczące wyświetlania). Jeśli chcielibyśmy postępować zgodnie ze sztuką, to powinniśmy mieć też osobną warstwę obiektów (DTO), które byłyby zwracane z Application, a następnie mapowane w WebUI na ViewModele. Ale ponieważ wymaga to więcej pracy, więc z klasy z projektu Application operują bezpośrednio na ViewModelach z projektu Contracts (one są w tym projekcie, aby uniknąć cyklicznej referencji między WebUI a Application).

Tylko że taki kompromis raczej nie nadaję się do WPFa, bo ViewModele realizują też logikę UI. Powinny więc znaleźć się w projekcie Desktop. Klasy z projektu Application realizują logikę APLIKACJI, a nie UI. Miejsce klas realizujących logikę UI jest również w projekcie Desktop. Jeśli chcesz zachować podział między warstwami, to powinieneś utworzyć w Application osobne DTO, np. CreateX, XDto, GetX, na których będą operować klasy z tego projektu. Skoro już masz tę osobną warstwę obiektów, to możesz skorzystać sobie z biblioteki MediatR, aby ułatwić sobie komunikację między Desktop a Application. Tu przykładowy kontroler w ASP.NET Core korzystający z tej biblioteki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0