Search code examples
c#wpfmvvmdependency-injectionsimple-injector

Injecting data resolved models at runtime with Simple Injector


I am building an app with Simple Injector in WPF and I have run into the issue where I want to resolve my Models to inject into my ViewModels at runtime. For instance, say I have a window to edit users that requires a ViewModel with a User Model. This user model is selected from a list and then injected into the ViewModel's constructor. How would I get this data into the ViewModel with Simple Injector? Is that even possible? I figure if it is possible I would use some form of factory maybe? I was debating on using Simple Injector for everything except my MVVM components as a workaround--that is unless I can find a good solution.

If I should post some example code or anything like that to give a more clear definition of the problem, let me know. This is my first run with a DI Container and I want to understand how to best design my application with one.


Solution

  • Using the prefered approach what you're aiming for is indeed not possible. That is because your design is not optimal. As you can read here injecting runtime data in the components of your application is an anti-pattern.

    The model for editing your users is runtime data and should thus flow through your application via method injection.

    So you could solve this like:

    public interface IViewModel<T>
    {
        void EditItem(T item);
    }
    
    class UserEditViewModel : IViewModel<User>
    {
        public void EditItem(User item)
        {
            // bind properties etc...
        }
    }
    

    You would typically inject the IViewModel<User> in your user master viewmodel.

    Based on this and this design you can imagine a far more flexible solution. If you would see editing a user as performing a command which you just fire and returns when it's finished, you could define a infrastructal component a la the QueryProcessor from the link. This would become an EditProcessor which handles all your edit operations in your application. An implementation is pretty simple and would look something like:

    class EditProcessor : IEditProcessor
    {
        private readonly Container container;
    
        public EditProcessor(Container container)
        {
            this.container = container;
        }
    
        public void EditItem<T>(T item)
        {
            var viewModel = typeof (IViewModel<>).MakeGenericType(typeof (T));
            dynamic instance = container.GetInstance(viewModel);
    
            instance.EditItem((dynamic) item);
        }
    }
    

    Now everywhere you need to edit some model, you only inject IEditProcessor and call

    this.editProcessor.EditItem(yourItem);
    

    This simple implementation of an EditProcessor can be extended will all kinds of nice features like making a backup of the item before editing, so the user could cancel the editform for example.

    If you use some MVVM toolkit to bind your view to your viewmodel this would also be the place to bring your DI container and the MVVM toolkit interact with eachother nicely.