Search code examples
c#dependenciesinversion-of-controlcode-injection

C# Dependency Injection - good practices


I have some problem with understanding how to create injectable classes…

Here is my example:

public interface IService
{
  string FindSomeData()
}

Now we create a class which implements the interface:

public class FolderService : IService
{
  private string _path;

  public FolderService(string path)
  {
    _path = path;
  }

  public string FindSomeData()
  {
    //Open a folder using _path and find some data
  }
}

And maybe other class:

public class DbService : IService
    {
      private MyConnectionClass _connection;

      public DbService(MyConnectionClass connection)
      {
        _connection = connection;
      }

      public string FindSomeData()
      {
        //Connect to database using _connection object and find some data
      }
    }

Now I would like to add one of the classes to IoC Container e.x.:

if (InDebug)
 SimpleIoc.Default.Register<IService, FolderService>();
else
 SimpleIoc.Default.Register<IService, DbService>();

And know I have a problems. When I want to pass this object to the constructor of some other classes:

public MyViewModel(IService service)
{
 _service = service;
}
// Read folder name from TextBox on View and then call _service.FindSomeData

Then I would like to pass user selected path to the IService object (FolderService) in this case. How should I do this in a correct way (according to SOLID and other good practiciess patterns…)?

Once I should pass string (folder path), once a MyConnectionClass (if connection to database). What is the best way to do that kind of things?

Best regards, Michal


Solution

  • You can encapsulate folder path provide/change logic into a separate provider like IFolderPathProvider and inject it into FolderService

    public interface IFolderPathProvider {
        string GetFolderPath();
        void SetFolderPath(string);
    }
    
    public class FolderPathProvider : IFolderPathProvider  {
        ...
    }
    
    public class FolderService : IService
    {
      private IFolderPathProvider _folderPathProvider;
    
      public FolderService(IFolderPathProvider folderPathProvider)
      {
        _folderPathProvider = folderPathProvider;
      }
    
      public string FindSomeData()
      {
        string path = _folderPathProvider.GetFolderPath();
        //Open a folder using path and find some data
      }
    }
    

    When user changes the path, inject IFolderPathProvider to the handler and call SetFolderPath. Similarly, you can create IDbConnectionProvider. Depending on the situation, they can be combined into one DataConfigProvider but I 'm not sure what exactly do you need there; the main idea is to separate folderpath/dbconnection changing logic from the services and keep using dependency injection.