简体   繁体   中英

Dependency injection and many implementations of interface

I have a small problem with using dependency injection in my project. To describe problem I will use simple example. Let's assume that I'm writing logger aplication and my end user is able to choose if log should be saved to file or written to the console. User control it by choosing checkboxes in running app. He can select both or only one. After selecting he clicks button "LOG" to perform action. Now what I understand from my knowledge of DI I should create interfaces:

public interface ILogger
{ 
   void log();
}

And two implementations

public class ConsoleLogger : ILogger
{
    public void log()
    {
      ...
    }
}

public class FileLogger : ILogger
{
    public void log()
    {
      ...
    }
}

I know that I can register both implementations in for example unity container and get them in constructor by using table but then I can't identify which implementations is FileLogger and which is ConsoleLogger (In case when user select only one checkbox)

Second options is use service locator pattern to resolve implementations from ioc by name. I dont know if it is a good approach

In my real application I will have more options than two and there will be a lot of shared interfaces by each option.

Maybe better is use MEF?

Application will be written in WPF + PRISM.

The way I usually do this is to make your class depend on an ILoggerFactory , which can create ILogger instances given a name.

The factory implementation, LoggerFactory , would hold the container's kernel and be able to resolve the component by name.

Notice how the factory interface only tells you that it can create objects - it doesn't give you any hint about any underlying kernel, or DI framework - the factory implementation is the one that knows about those details.

Something like this:

public class MyLoggingClass
{
    private readonly ILoggerFactory _loggerFactorty;

    public MyLoggingClass(ILoggerFactory factory)
    {
        _loggerFactorty = factory;

        var fileLogger = _loggerFactorty.Create("fileLogger");
        var consoleLogger = _loggerFactorty.Create("consoleLogger");
    }
}


public class LoggerFactory : ILoggerFactory
{
    public ILogger Create(string key)
    {
        return kernel.Resolve<ILogger>(key);
    }
}

Frameworks like Castle Windsor even give you these factories for free: you don't even have to write its implementation.

Service locator pattern is an anti-pattern now and should not be used.

In your case, it's better to use Strategy design pattern because you're creating objects dynamically at runtime.

The differences between dependency injection and strategy pattern are subtle but there are. For more information:

Strategy Pattern vs Dependency Injection

What is the difference between Strategy pattern and Dependency Injection?

To create objects dynamically, you could use factory method design pattern or abstract factory .

I don't see the point of creating a custom factory if all you want is basic IOC functionality. If you're going to develop the application using WPF and Prism, a good approach is to use one of the supported IOC containers. I have used Unity a lot and really like it. Another supported version is the MEF (as you suggested).

Both of them allow you to resolve interfaces using names. It is not bad practice and gives a structured way of resolving the correct interface.

For using Prism with Unity or Mef, see here:

https://docs.microsoft.com/en-us/previous-versions/msp-np/gg430868(v=pandp.40)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM