senz
senz

Reputation: 879

IOC - How to handle changing dependencies

Lets assume we have the following service class:

PersonService.cs

public class PersonService : IPersonService
{
    private readonly IPersonRepository _repository;

    public PersonService(IPersonRepository repository)
    {
        _repository = repository;
    }

    /* Interface members here... */
}

This service class depends on IPersonRepository. In our example this repository will handle a file connection:

FilePersonRepository.cs

public class FilePersonRepository : IPersonRepository
{
    private readonly string _filePath;

    public FilePersonRepository (string filePath)
    {
        _filePath = filePath;
    }

    /* Interface members here... */
}

This repository depends on a file path, which is needed to determine which file should be handled in this repository.

These classes are wired in a container:

public static void ConfigureContainer(MyIocContainer container)
{
    container.Register<IPersonRepository, FilePersonRepository>(@"C:\temp\file.txt");
    container.Register<IPersonService, PersonService>();
    container.Register<MainViewModel>();
}

Now, everything is fine if i use a static path (for example in a config file), which is injected only once into this class constructor.

But what happens if i have a ViewModel, which persists along the whole application, and this one is using the registered service class. And the file path must be changebale by an open-folder dialog. How to handle this?

I think using a Property with get/set in my repository or create a class which refers the path on a static string may not so clean.

Any suggestions?

Upvotes: 1

Views: 70

Answers (1)

sANDwORm
sANDwORm

Reputation: 189

There are many solutions how to solve your problem and it is impossible to say which one is the best. But I am quite sure that best practice is to avoid dynamic dependencies.

I personally would do it this way:

public interface IRepositoryConnectionString
{
    void SetConnectionString(string connectionString);
}

public interface IPersonRepository : IRepositoryConnectionString ...

public class FilePersonRepository : IPersonRepository
{
    /* file related private fields here */

    public FilePersonRepository ()
    {
        SetConnectionString(ConfigurationManager.ConnectionStrings[
            "FilePersonRepository.ConnectionString"]);
    }

    public SetConnectionString(string connectionString)
    {
         /* do all required stuf like flush previous file, open file, etc...  */ 
    }

    /* Interface members here... */
}

Almost every storage have some kind of connection string, so this interface shall be applicable to the majority of other possible implementations (Mongo, SQL, Azure Table).

Your application bootstrap could specify what configuration dialog is to be used. For example as:

container.Register<IPersonRepositoryConfigurationDailog, FileRepositoryConfigurationDialog>();

Upvotes: 1

Related Questions