Implementing Dependency injection static methods

隐身守侯 提交于 2021-02-04 15:45:20

问题


In this old code I am trying to update , they implemented dependency injection like this:

public class Program
{
    private IProgramRepository programRepository;

     public Program(IProgramRepository repository)
        {
             this.programRepository = repository;
        }

     public Program() : this(new EN_Program()) { }

now in this program class all methods are static, so all of the static methods all actually have 2 methods like this:

    public static List<Program> GetProgramsByUser(int userId)
    {
        return GetProgramsByUser(userId, GetDefaultRepository());
    }
    private static List<Program> GetProgramsByUser(int userId, IProgramRepository repo)
    {
        return repo.GetProgramsByUser(userId);
    }

Now I've read this among other things about implementing DI:

This is not dependency injection at all. This actually clearly violate the dependency inversion principle. The principle say that "High level module should not depend upon the low level module, both should depend on abstraction. Details should depends upon abstraction". In above code Product.cs itself create EN_Program object. So it directly depends on IProgramRepository implementation (EN_Program). If in future another implementation comes of IProgramRepository interface then Product.cs code itself need to change. So it is probed that it is not proper way to do.

It looks like the old developers wanted to implement DI just starting with the helper classes (Program.cs) with nothing injected into the controllers.

Am I correct in assuming that this old code was not written correctly ? Is it necessary when implementing DI that everything from the controller to the back end have injections?

ex. The controller would need to be injected with an Interface that the helper class uses (Program.cs) - then Program.cs is injected with an interface that the repository uses


回答1:


The comment is incorrect. It talks about Dependency Injection pattern, but it quotes the Dependency Inversion Principle. The overloaded constructor is an implementation of the Dependency Injection pattern, and the default constructor is an implementation of the Poor Man's Dependency Injection anti-pattern.

Although the overloaded constructor practices the Dependency Injection pattern, the default constructor does not and does in fact violates the Dependency Inversion Principle. Because of the reasons quoted.

So you're absolutely practicing Dependency Injection, but you are also practicing Poor Man's Dependency Injection which is bad for a lot of reasons. For instance:

  • Your code takes a direct dependency on a low level component disallowing you to ship them separately.
  • The direct dependency makes it harder to swap implementations, which is something that is very common to do when you add cross-cutting concerns (using decorators or interceptors) . You don't want to go through the whole application to change all constructors just to wrap EN_Program instances with a decorator or interceptor.



回答2:


The first method is depending on a factory method (I hope). Inside this factory method an IProgramRepository is created. This function is not depending on anything but the factory method itself.

public static List<Program> GetProgramsByUser(int userId)
{
    return GetProgramsByUser(userId, GetDefaultRepository());
}

The second method is also not depending on an other class. The depencing is "given" in a parameter.

private static List<Program> GetProgramsByUser(int userId, IProgramRepository repo)
{
    return repo.GetProgramsByUser(userId);
}

EDIT

Officially Depenency Injection (DI) is a subset of Inversion of Control (IoC) and these terms are mixed up sometimes. Perhapse officially your code does not realy follow the rules of DI, but it is IoC for sure!



来源:https://stackoverflow.com/questions/16282223/implementing-dependency-injection-static-methods

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