How to inject dependency to static class

最后都变了- 提交于 2020-01-03 17:46:07

问题


I've been making simple logger class with DI but I have some problem and question.

There is a problem. If I make a logger class with DI. I should use it like this whenever I use it.

var logger = new LogService(new FileLogger());
logger.WriteLine("message");

I want to make it to static class, but there is no way to inject dependency by constructor in static class.

So, I change it like this.

public static class LogService()
{
    private static readonly ILoggable _logger;
    static LogService()
    {
         _logger = new FileLogger();
    }
}

I think this is so weird. This is not DI..

Isn't there a good way to inject dependency to static class?

Thank you.


回答1:


Dependency Injection, as a practice, is meant to introduce abstractions (or seams) to decouple volatile dependencies. A volatile dependency is a class or module that, among other things, can contain nondeterministic behavior or in general is something we which to be able to replace or intercept. For a more detailed discussion about volatile dependencies, see section 1.3.2 of this freely readable introduction of this book.

Because your FileLogger writes to disk, it contains nondeterministic behavior. For this reason you introduced the ILoggable abstraction. This allows consumers to be decoupled from the FileLogger implementation.

To be able to successfully decouple a consumer from its volatile dependency, however, we need to inject that dependency into the consumer. There are three common patterns to choose from:

  • Constructor Injection—Dependencies are statically defined as list of parameters to the class's instance constructor.
  • Property Injection—Dependencies are injected into the consumer via writable instance properties.
  • Method Injection—Dependencies are injected into the consumer as method parameters.

Both Constructor Injection and Property Injection are applied inside the Composition Root and require the consumer to store the dependency in a private field for later reuse. This requires the constructor and property to be instance members, i.e. non-static. Static constructors can't have any parameters and static properties lead to the Ambient Context anti-pattern (see chapter 5.3 of this book), and Temporal Coupling. This hinders testability and maintainability.

Method injection, on the other hand, is applied outside the Composition Root and it does not store any supplied dependency, but instead merely uses it. Method injection can, therefore, be applied to both instance and static methods. In that case, the method's consumer must supply the dependency. This does mean, however, that itself must have been supplied with that dependency either through constructor, property or method injection.

Your example of the static LogService that created FileLogger inside its constructor is a great example of strongly coupled code. This is known as the Control Freak anti-pattern (chapter 5.1) or in general can be seen as a DIP violation. This is the opposite of DI.

To prevent strong coupling of volatile dependencies, the best is to make LogService non-static and inject its volatile dependencies into its sole public constructor.




回答2:


Why you want to to use inject dependency and Static Class at sometime ?

public static class LogService
{
    private static ILoggable _logger;
    public static ILoggable Logger
    {
        get
        {
             return _logger;
        }
    }
    public static InitLogger(ILoggable logger)
    {
         _logger = logger;
    }
}

And You Need Init First Like This

LogService.InitLogger(new FileLogger());

LogService.Logger.WriteLine("message");


来源:https://stackoverflow.com/questions/52325438/how-to-inject-dependency-to-static-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!