实现依赖注入的静态方法

5

在我试图更新的这段旧代码中,他们是这样实现依赖注入的:

public class Program
{
    private IProgramRepository programRepository;

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

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

现在在这个程序类中,所有的方法都是静态的,所以实际上所有的静态方法都像这样有两种方法:
    public static List<Program> GetProgramsByUser(int userId)
    {
        return GetProgramsByUser(userId, GetDefaultRepository());
    }
    private static List<Program> GetProgramsByUser(int userId, IProgramRepository repo)
    {
        return repo.GetProgramsByUser(userId);
    }

我已经阅读了关于实现DI的其他内容:

这根本不是依赖注入。这实际上明显违反了依赖倒置原则。该原则指出,“高级模块不应依赖低级模块,两者都应依赖抽象。详细信息应依赖于抽象”。在上面的代码中,Product.cs本身创建了EN_Program对象。因此,它直接依赖于IProgramRepository实现(EN_Program)。如果将来另一个IProgramRepository接口的实现出现,则Product.cs代码本身需要更改。所以可以证明这不是正确的方法。

看起来旧的开发人员想要实现DI,只从帮助类(Program.cs)开始,没有将任何东西注入到控制器中。

我是否正确地认为旧代码编写不正确?在实现DI时,是否有必要将从控制器到后端的所有内容都注入?

例如,控制器需要注入一个帮助类使用的接口(Program.cs)-然后将Program.cs注入一个存储库使用的接口

2个回答

7
该评论有误。它谈论了依赖注入模式,但引用的是依赖反转原则。重载构造函数是依赖注入模式的实现,而默认构造函数是贫民依赖注入反模式的实现。
虽然重载构造函数实践了依赖注入模式,但默认构造函数并没有,并且事实上违反了依赖反转原则。因为引用的原因。
所以,您绝对在实践依赖注入,但您也在实践贫民依赖注入,这对许多原因来说都是不好的。例如:
- 您的代码直接依赖于低级组件,使您无法单独地进行部署。 - 直接依赖关系使得更换实现变得更加困难,而更换实现在添加横切关注点(使用装饰器或拦截器)时非常常见。您不希望遍历整个应用程序,只是为了使用装饰器或拦截器来包装EN_Program实例而更改所有构造函数。

@Scott Selby 在 @Steven 的优秀文章基础上,如果你想避免每次获取 Program 实例时都提供依赖项(或始终通过 DI 容器获取 Program 实例),则可以使用 服务定位器。如果您有许多类都依赖于某个存储库,则这是非常合理的;构造函数注入通过显式声明此依赖关系没有增加任何价值,因为它已经是一个明显的依赖关系。 - Masood Khaari

1
第一种方法是依赖于工厂方法(我希望如此)。在这个工厂方法内部创建了一个IProgramRepository。这个函数不依赖于任何东西,只依赖于工厂方法本身。
public static List<Program> GetProgramsByUser(int userId)
{
    return GetProgramsByUser(userId, GetDefaultRepository());
}

第二种方法也不依赖于其他类。依赖关系在参数中“给定”。
private static List<Program> GetProgramsByUser(int userId, IProgramRepository repo)
{
    return repo.GetProgramsByUser(userId);
}

编辑

官方地说,依赖注入(DI)是控制反转(IoC)的一个子集,有时这些术语会混淆。也许你的代码并没有严格遵循 DI 的规则,但它肯定是 IoC!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接