Search code examples
wpfdependency-injectioncastle-windsor

Optional Dependency at Composition Root


I've written a WPF app that has two different main windows. I don't know which one to launch until runtime by looking up what kind of user is using the program in a database. The code I currently have works but Castle Windsor is doing tons of extra work by newing up the object graphs for both kinds of windows.

    private readonly IMainWindow _mainWindow;
    private readonly ISimplifiedMainWindow _simplifiedMainWindow;

    public MainClass(
        IMainWindow mainWindow,
        ISimplifiedMainWindow simplifiedMainWindow)
    {            
        _mainWindow = mainWindow;
        _simplifiedMainWindow = simplifiedMainWindow;
    }

    public RunApp()
    { // pseudocode
        if (user is fullUser) _mainWindow.Show();
        else _simplifiedMainWindow.Show();
    }

How do I defer creation of my window objects without resorting to making an abstract factory that will basically duplicate what Castle Windsor does anyway?


Solution

  • A factory is in fact the solution I'd recommend (and a solution I've successfully used multiple times in the past to solve this very problem).

    I wouldn't implement the factory myself though, let Windsor do it (via a Typed Factory).

    public interface IWindowFactory
    {
       IMainWindow FullUserWindow();
       ISimplifiedMainWindow SimplifiedUserWindow();
    
       //optionally
       void DestroyWindow(IWindow window);
    }
    

    Now you just need to tell Windsor to build a factory for that interface

    container.AddFacility<TypedFactoryFacility>();
    // later on, in your installer
    container.Register(Component.For<IWindowFactory>()
                          .AsFactory()
                          .LifestyleTransient());
    

    and your app code changes to:

    public RunApp()
    { // pseudocode
        if (user is fullUser) Show(factory.FullUserWindow());
        else Show(factory.SimplifiedUserWindow());
    }