簡體   English   中英

忍者。 可選注入

[英]Ninject. Optional Injection

我有啟用/禁用功能的全局標志。 我想根據某些標志注入一些依賴項。 某些功能需要大量構建的類,因此如果標志的值為 false,則我想注入 null,否則為實際依賴項。 Ninject 不允許注入 null。 還有其他選擇嗎?

更新:構造函數 arguments 可以用OptionalAttribute屬性裝飾。 在這種情況下,如果沒有找到相應的綁定,則注入 null。 這里有一個問題:我無法驗證目標 class 是否可以正確構建。 我對每個公共依賴項進行了測試,以驗證它是否可以成功構建。 如果標志的值為 true,當使用OptionalAttribute屬性裝飾的依賴項無法正確構造時,我將無法找到錯誤。 我只想在綁定級別上管理它。

您可以通過使用工廠方法(即ToMethod )綁定來改變注入行為,並且可以通過配置容器的AllowNullInjection設置來允許注入空值。

另一種選擇是使用工廠方法並提供輕量級虛擬 object 而不是重量級 class。 如果您使用的是接口,這將很簡單,只需實現不執行任何操作的接口即可。 您甚至可以使用 FakeItEasy 等 mocking 框架為您構建這些假人。 這里的好處是,假人使特殊行為對客戶端透明,即客戶端不需要檢查null等。

使用工廠方法的示例,加上AllowNullInjection和 nulls:

public void Configure()
{
    bool create = true;

    IKernel kernel = new StandardKernel();

    kernel.Settings.AllowNullInjection = true;

    kernel.Bind<IFoo>().ToMethod(ctx => create ? ctx.Kernel.Get<Foo>() : null);

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>();
}

private interface IFoo {}

private class Foo : IFoo {}

private class DependendsOnIFoo
{
    public DependendsOnIFoo(IFoo foo) {}
}

還有一個根據標志替換輕量級 object 的示例:

public void Configure()
{
    bool heavy = true;

    IKernel kernel = new StandardKernel();

    kernel.Bind<IFoo>()
     .ToMethod(ctx => heavy ? ctx.Kernel.Get<HeavyFoo>() : (IFoo)new DummyFoo());

    DependendsOnIFoo depFoo = kernel.Get<DependendsOnIFoo>();
}

private interface IFoo {}

private class HeavyFoo : IFoo {}

private class DummyFoo : IFoo { }

private class DependendsOnIFoo
{
    public DependendsOnIFoo(IFoo foo) {}
} 

注入 null 通常不是一個明智的主意。 這將通過檢查 object 是否為 null 來污染您的代碼,如下面的代碼所示:

public interface IFoo
{
    void Do();
}

public class Foo : IFoo
{
    public void Do()
    {
       DoSomething();
    }
}

public class UglyNullCheckingBar
{
    IFoo foo;
    public Bar(IFoo foo)
    {
        this.foo = foo;
    }

    public void Do()
    {
        if (this.foo != null)
        {
            this.foo.Do();
        }
    }
}

在這種情況下,更好的方法是實現一個 Null Object ,它完全不做任何事情並注入這個而不是 null。 這使您的代碼保持干凈。

public class NullFoo : IFoo
{
    public void Do() {}
}

public class Bar
{
    IFoo foo;
    public Bar(IFoo foo)
    {
        this.foo = foo;
    }

    public void Do()
    {
        this.foo.Do();
    }
}

暫無
暫無

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

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