资产注入是否被认为是不好的? [英] Is property injection considered to be bad?

查看:110
本文介绍了资产注入是否被认为是不好的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用于演示该问题的示例解决方案:

Example solution to demonstrate the problem:

class World
{
    public override string ToString()
    {
        return "Hello World";
    }
}
class Hello
{
    [Inject]
    public World theWorld {  get;  set; }
    public Hello(IKernel kernel)
    {
        kernel.Inject(this);
    }
    public override string ToString()
    {
       return theWorld.ToString();
    }
}
class Program
{
    static IKernel kernel = new StandardKernel();
    static void RegisterServices()
    {
        kernel.Bind<World>().ToSelf();
    }
    static void Main(string[] args)
    {
        RegisterServices();
        Hello hello = new Hello(kernel);
        Console.WriteLine(hello.ToString());
        Console.ReadLine();
    }
}

这是我使属性注入真正起作用的方式.

This is the way I got property injection actually working.

如果满足以下条件,它将无法正常工作

It won`t work if:

  1. 财产不是公开的(或其设定者).
  2. 要求注入的类未获取IKernel实例来调用kernel.Inject(this);.

对我来说,这样做似乎很多余,而且仅获取属性实例是错误的.有没有更简单的方法,或者我还没有考虑过什么?

For me its seems very excess and wrong to do this only to get instance of a property. Are there simpler ways or I haven't considered something?

推荐答案

属性注入通常很糟糕,因为它会导致时间耦合.属性注入仅应用于真正可选的依赖项(在您的情况下不是).但是,依赖关系几乎永远都不是可选的.即使没有依赖项的实现,也最好创建并注入空对象实现,而不是注入null引用.与其使用属性注入,不如通过构造函数注入所有必需的依赖项.

Property injection is typically bad since it causes Temporal Coupling. Property injection should only be used for dependencies that are truly optional (which it isn't in your case). Dependencies, however, should hardly ever be optional. Even in case there is no implementation for a dependency, it's better to create and inject a Null Object implementation than injecting a null reference. Instead of using Property Injection, prefer injecting all required dependencies through the constructor.

另一个不好的做法是让您的应用程序代码依赖于容器本身(或代表容器的resolve-API的抽象).这是一个称为服务定位器的反模式.您应该引用容器的唯一位置是您的组合根 .您的示例中的Program类表示合成根.

Another bad practice is letting your application code take a dependency on the container itself (or an abstraction that represents the resolve-API of the container). This is an anti-pattern called Service Locator. The only place you should reference the container is in your Composition Root. The Program class in your example represents the Composition Root.

相反,您的Hello类应该只接受World作为必需的构造函数参数:

Instead your Hello class should simply accept World as required constructor argument:

class Hello
{
    private readonly World theWorld;

    public Hello(World theWorld)
    {
        this.theWorld = theWorld ?? throw new ArgumentNullException("theWorld");
    }

    public override string ToString()
    {
        return this.theWorld.ToString();
    }
}

请注意,我是如何从此类完全删除对容器的任何引用的.这使类更简单,更可维护,更可测试,甚至可以在不使用DI容器工具的情况下组成该类.一种通常称为纯DI 的做法.当您的应用程序较小时,与使用容器相比,Pure DI可能是更好的选择.

Notice how I completely removed any reference to the container from this class. This makes the class simpler, more maintainable, more testable, and even makes it possible to compose this class without using a DI container tool; a practice commonly known as Pure DI. When your application is small, Pure DI can be a better option than using a container.

Program类的外观如下:

class Program
{
    static void Main(string[] args)
    {
        // Configure
        var kernel = new StandardKernel();
        kernel.Bind<Hello>().ToSelf();
        kernel.Bind<World>().ToSelf();

        // Resolve
        var hello = kernel.Get<Hello>();

        // Use
        Console.WriteLine(hello.ToString());
        Console.ReadLine();
    }
}

没有容器,将如下所示:

Without a container, it would be as follows:

class Program
{
    static void Main(string[] args)
    {
        // Resolve
        var hello = new Hello(new World());

        // Use
        Console.WriteLine(hello.ToString());
        Console.ReadLine();
    }
}

这篇关于资产注入是否被认为是不好的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆