Dependency Injection und Designtime-Support

  • WPF MVVM
  • .NET 5–6

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Amro.

    Dependency Injection und Designtime-Support

    Hey Leute,

    ich beschäftige mich gerade mit Dependency Injection und habe ein kleines Problem: Mein Designer unterstützt mich nicht richtig während der Designzeit. Scheint so, als ob er nur den Standardkonstruktor aufruft und meine gewünschten Klassen nicht injiziert werden. Das ist natürlich super frustrierend!

    Hat jemand von euch schon einmal was damit gemacht. Vielleicht gibt es einen Trick, um den Designer davon zu überzeugen, dass er mir auch während der Entwurfszeit die injizierten Klassen zur Verfügung stellt.


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amro“ ()

    Wenn vom DesignTime-Teufel gesprochen wird...

    Moinsen. Ich war gerade im Discord und habe mit @EaranMaleasi dasselbe Thema besprochen.

    Da es die Regel gibt das auch im Forum zu posten, wollte ich gerade auf "neues Thema" drücken, und da sah ich diesen Beitrag.

    Daher werde ich hier mein Problem schildern und meine Teil-Lösung gleich mit.

    Einleitung:
    WPF mit MVVM (leider in C#).

    DependencyInjection von MS per Nuget-Paket

    Quellcode

    1. Microsoft.Extensions.DependencyInjection

    und

    Quellcode

    1. Microsoft.Extensions.Hosting

    Dazu als MVVM-Framework

    Quellcode

    1. CommunityToolkit.Mvvm



    Ziel ist es, eine Settings-Klasse in das MainWindowViewModel mittels Kontruktor-Injektion (ISettings settings), einzuschleusen.

    Das geht so weit, aber dann motzte der liebe XAML-Designer, dass mein Designtime-Datacontext, keinen Parameterlosen-Konstruktor gefunden hat.

    XML-Quellcode

    1. xmlns:viewModels="clr-namespace:AssemblyName.ViewModels"
    2. d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,
    3. Type={x:Type viewModels:MainWindowViewModel}}"


    Was mir dann geraten wurde, einfach zwei Konstruktoren zu nutzen. Einmal mit und einmal ohne alles (aber mit scharfe Sauce).

    VB.NET-Quellcode

    1. [ObservableProperty]
    2. private ISettings settings; // Achtung! MVVM.Toolkit sieht vor, dass die Deklaration als Feld (kleingeschrieben) geschehen soll,
    3. // dann generiert der Compiler den Rest (Eigenschaft/Property mit INofitfyPropertyChanged),
    4. // und angesprochen wird es dann großgeschrieben => 'settings erzeugt Settings'.
    5. public MainWindowViewModel()
    6. {
    7. Settings = new Settings();
    8. Settings = Settings.ReadSettingsFile();
    9. }
    10. public MainWindowViewModel(ISettings settingsParameter)
    11. {
    12. Settings = settingsParameter;
    13. Settings = Settings.ReadSettingsFile();
    14. }


    Und jetzt ist der Designer zufrieden ...

    Ich überlege, ob ich das noch in eine 'Init()'-Operation verschieben sollte.


    Hier einmal meine App.xaml.cs (Programm-Start-Datei) mit dem DI-Container/-Resolver

    VB.NET-Quellcode

    1. public partial class App : Application
    2. {
    3. public static IHost AppHost { get; private set; }
    4. public App()
    5. {
    6. AppHost = Host.CreateDefaultBuilder()
    7. .ConfigureServices((hostcontext, services) =>
    8. {
    9. // Services hier anlegen... Kommentarlos bleibt dieser Kommentar :)
    10. services.AddSingleton<ISettings, Settings>();
    11. services.AddSingleton<MainWindow>();
    12. services.AddSingleton<MainWindowViewModel>();
    13. })
    14. .Build();
    15. }
    16. protected override async void OnStartup(StartupEventArgs e)
    17. {
    18. await AppHost!.StartAsync();
    19. var mainWin = AppHost.Services.GetRequiredService<MainWindow>();
    20. //mainWin.DataContext = AppHost.Services.GetRequiredService<MainWindowViewModel>();
    21. mainWin.Show();
    22. base.OnStartup(e);
    23. }
    24. protected override async void OnExit(ExitEventArgs e)
    25. {
    26. await AppHost!.StopAsync();
    27. base.OnExit(e);
    28. }
    29. }


    Hier die MainWindow (View) für DataContext

    VB.NET-Quellcode

    1. public partial class MainWindow : Window
    2. {
    3. public MainWindow(MainWindowViewModel ViewModel)
    4. {
    5. InitializeComponent();
    6. DataContext = ViewModel;
    7. }
    8. }


    Wichtig! In der App.xaml muss das Atrribut StartupUri entfernt werden.

    XML-Quellcode

    1. <Application StartupUri="Views/MainWindow.xaml">
    2. <Application.Resources />
    3. </Application>


    XML-Quellcode

    1. <Application >
    2. <Application.Resources />
    3. </Application>



    Das sind meine 2-Pfennig zum Thema. Ich hoffe, das hilft ein wenig ...

    c.u. Joshi aus der Independency-Hölle :)
    Hallo Joshi,
    das ist gut,
    ich benutze auch die Microsoft.Extensions und C#.
    In deine Fall ist es noch einfach.
    Aber wenn du mehrer Klassen hast und viele diese Klassen auch Dependency haben, kann dein Ansatz schnell
    Unübersichtlich werden. Man macht das ja mit den DI-Container damit man in der App.cs ein zentralen Punkt hat, wo man seine Abhängigkeiten organisieren kann.Fängst du jetzt mit new und dann noch in einen zweiten Konstruktor an, und dann für alle deine klassen ,Services und soweiter. Dann hast du nix gewonnen. Du stehst dann wieder da, wo du vorher entkopplen wolltest.
    Was ich gelesen hab und was besser für in deine Fall wäre , ist ein Ordner in Views. Den nennt man dann DesingTimeSupport oder so und Arbeitet dann mit den DesingtimeViewmodels zu Desingtime.
    Aber irgendwann kommst du an den ServiceProvider um Views abzurufen, dann wirds wieder komplex.
    Das ist der Punkt an dem ich gerade bin.
    Eigentlich müsste ich

    C#-Quellcode

    1. AppHost!.StartAsync();
    zu DesingTime starten können. Ich weiß aber noch nicht wie. Oder am besten die ganze App.cs irgendwie zu laufzeit oder so. Aber ich finde keine Lösung.
    Das Hot-Reload Hilft einwenig. In MAUI gibts auch noch kein DesingtimeSupport und da ist DI-Container von Haus drin.Warcheinlich wird man nur mit ein Minimum und wichtigen Desingtime-Daten arbeitet wenn man Injection benutzt glaub ich. Anders kann ich mir das nicht vorstellen im Moment.
    Aber schön das du dich auch auf die gleiche Weise mit dem Thema beschäftigst und auch die gleichen Probleme siehst.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amro“ ()