2

My first attempt on using an IoC container. A program has a number of different type of windows that are typically opened through a menu in MainWindow. However, in principle it could also be further down the chain. These windows usually need injection of one or more singleton-classes, lets name them here IManager1/2/3. So, do I need to bubble these IManagers up through MainWindow, or can I resolve each window at the root (here in App class)?

In either case, how would this be done?

I don't need to use DryIoc, but that's just what I chose to test.

   public partial class App : Application
{
    DryIoc.Container container = new DryIoc.Container();

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        RegisterIoc();

        var mainwindow = new MainWindow(); 
        mainwindow.Show();
    }

    public void RegisterIoc()
    {
        container.Register<IManager1, Manager1>(Reuse.Singleton);
        container.Register<IManager2, Manager2>(Reuse.Singleton);
        container.Register<IManager3, Manager3>(Reuse.Singleton);
    }
}

public MainWindow()
{
    public MainWindow()
    {
    }

    void OpenNewWindow2()
    {
        var w = new Window2(?, ?, ?);
        w.Show();
    }
}

public class Window2
{
    IManager1 man1;
    IManager2 man2;
    IManager3 man3;

    public Window2(IManager1 man1, IManager2 man2, IManager3 man3)
    {
        this.man1 = man1;
        this.man2 = man3;
        this.man3 = man3;
    }
}
bretddog
  • 5,411
  • 11
  • 63
  • 111
  • It would be better in you use a mediator pattern to receive the window request and resolve it to have its dependencies injected and the window shown. – Nkosi Jul 04 '19 at 18:44
  • 1
    or if you want to use pure DI then inject a factory into the main window and have it resolve the desired window – Nkosi Jul 04 '19 at 18:45

1 Answers1

2

Consider following explicit dependency principle and making Window2 a dependency of MainWindow

For example

public class MainWindow {
    private readonly Func<Window2> window2;

    public MainWindow(Func<Window2> window2) {
        this.window2 = window2;
    }

    public void OpenNewWindow2() {
        var window = window2(); // invoke factory delegate
        window.Show();
    }
}

The above shows the use of a Func<T> as a factory delegate which will act as a wrapper for deferred resolution of the required dependency. Every time the factory delegate is invoked it will resolve a new instance of Window2, inverting the control of MainWindow having to initialize it manually;

The App.Application_Startup is used as the composition root where you would register every thing with the container and resolve the MainWindow, your root object

public partial class App : Application {
    DryIoc.Container container;

    private void Application_Startup(object sender, StartupEventArgs e) {
        container = RegisterIoc();    
        var mainwindow = container.Resolve<MainWindow>(); 
        mainwindow.Show();
    }

    private DryIoc.Container RegisterIoc() {
        var container = new DryIoc.Container();
        container.Register<MainWindow>();
        container.Register<Window2>();
        container.Register<IManager1, Manager1>(Reuse.Singleton);
        container.Register<IManager2, Manager2>(Reuse.Singleton);
        container.Register<IManager3, Manager3>(Reuse.Singleton);
        return container;
    }
}

Note that for the windows to be resolved you also need to make sure they are also registered with the container.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Looking at this. But as I have 10+ different window types, would I need to pass 10 factory delegates? That looks a bit cumbersome. Maybe this situation is better suited by a service locator? Currently I just reference the Manager-instances as static members of a Program class, directly from each Window class. But wanted to refactor out all UI elements (Windows, User controls) to a common library. – bretddog Jul 05 '19 at 09:42
  • @bretddog you could create some kind of window manager service or window factory responsible for resolving windows. – Nkosi Jul 05 '19 at 09:52