簡體   English   中英

財產注入被認為是壞事嗎?

[英]Is property injection considered to be bad?

演示問題的示例解決方案:

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();
    }
}

這就是我讓屬性注入實際工作的方式。

如果出現以下情況,它將不起作用:

  1. 屬性不是公開的(或其設置者)。
  2. 要求注入的類沒有得到 IKernel 實例,調用kernel.Inject(this); .

對我來說,這樣做只是為了獲得一個屬性的實例似乎是非常多余和錯誤的。 有沒有更簡單的方法,或者我還沒有考慮過什么?

構造函數注入通常是比屬性注入更有利的技術,因為屬性注入會導致 時間耦合代碼異味 因此,屬性注入應該僅用於真正可選的依賴項(這不是您的情況)。 然而,依賴性幾乎不應該是可選的。 即使沒有依賴項的實現,與注入null引用相比,創建和注入空對象實現通常更好。 與其使用屬性注入,不如通過構造函數注入所有必需的依賴項。

另一個導致相當大缺點的做法是,當您讓應用程序代碼依賴於 DI 容器本身(或表示容器的解析 API 的抽象)時。 這是一種稱為Service Locator的反模式。 您應該引用容器的唯一位置是在您的Composition Root 內 您示例中的Program類代表 Composition Root。

相反,您的Hello類應該簡單地接受World作為必需的構造函數參數:

class Hello
{
    private readonly World theWorld;

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

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

請注意如何從此類中完全刪除對容器的任何引用。 這使得類更簡單、更易於維護、更易於測試,甚至可以在不使用 DI 容器的情況下組合此類; 一種通常稱為Pure DI的做法。 當您的應用程序很小時,Pure DI 甚至可以是比使用容器更好的選擇。

以下是您的Program類在使用 Ninject 時的樣子:

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();
    }
}

如果沒有容器,它將如下所示:

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM