Search code examples
c#wpfdependency-injection

How to set the dependency injection when it depends of the selection of user at startup in a WPF application?


When I see some examples about how to use dependency injection in a WPF application, I have seen that this is configure in the app.xaml.cs file, that it is execute before any window is showed.

But in my case, some dependencies depends on the selection of the user in the first windows.

This is the case. I want to have an application that allow to upload and download files from two different clouds. The user selects from a dropbox which cloud he wants to use. Once it is selected, the whole application will use the selected cloud. If the user wants to use the other cloud, he has to close and run the application again (it is a bit silly behaviour, but it is to simplify and I think it expose the doubt better).

How the user need to select the cloud, I can't configure the dependency in the app file.

My code is this:

interface ICloudService
{
    UploadFile(string pathFileToUpload);
    DownloadFile(string pathToSaveFile);
}

class CloudOneService() : ICloudService
{
    //Implementation
}

class CloudTwoService() : ICloudService
{
    //Implementation
}

In the app.xaml.cs file, I should to configure the dependencies, something like that:

public partial class App : Application
{
    public App()
    {
        host = new HostBuilder()
          .ConfigureServices((hostContext, services) =>
          {
              services.AddScoped<ICloudService, CloudOneService>();
 
          }).Build();
    }
}

But this code first it will use always CloudOneService and second, it is run before the user can select the cloud.

So I am not sure how could I configure the dependency injection when it depends on the selection of the user.

How could I do it?

Thanks.


Solution

  • So, as I see it, your application has two states:

    1. where the user did not yet select something and
    2. after the selection happened

    Now, the question is: Do you need the interface to be available in state 1? If yes, then you should provide "something" there. If no, then you can easily resolve it when going into state 2, e.g. by using a factory class, like you suggested.

    enum CloudServiceType
    {
        One,
        Two
    }
    
    interface ICloudServiceFactory
    {
        ICloudService GetService(CloudServiceType selectedCloud);
    }
    

    If you need to have an ICloudService ready before the selection, you could either inject a "default" one using regular DI or just let the factory provide a default one with a GetDefault() method.