Unity,如何通过ParameterOverride传递null?

时间:2018-02-05 17:44:36

标签: c# dependency-injection unity-container

我想将null传递给已解析的类构造函数参数之一。但是,ParameterOverride不接受null作为值(从实现看似null内部被解释为"未解析")。

我也尝试使用默认值提供参数或没有此参数的重载构造函数 - 但在这种情况下Unity总是抱怨,我没有为此参数提供值。

示例代码:

unityContainer.Resolve<MyClass>(new ParameterOverride(myField, null));

2 个答案:

答案 0 :(得分:1)

您可以使用一些方法来注入空依赖项(例如注入null的InjectionFactory),但我没有看到ParameterOverride的方法。可能有一种简单的方法可以做到这一点,但我没有立刻想到它。

但是,使用ParameterOverride注入null的一种方法是创建一个专门注入null的InjectionParameterValue。这将绕过Unity的空检查。它可能看起来像这样:

public class NullInjectionParameterValue : InjectionParameterValue
{
    public NullInjectionParameterValue(Type parameterType)
    {
        this.ParameterTypeName = parameterType.GetTypeInfo().Name;
    }

    public override bool MatchesType(Type t)
    {
        return !t.IsValueType || (Nullable.GetUnderlyingType(t) != null);
    }

    public override IResolverPolicy GetResolverPolicy(Type typeToBuild)
    {
        return new LiteralValueDependencyResolverPolicy(null);
    }

    public override string ParameterTypeName { get; }
}

public class NullInjectionParameterValue<TParameter> 
    : NullInjectionParameterValue where TParameter : class
{
    public NullInjectionParameterValue()
        : base(typeof(TParameter))
    {
    }
}

然后你可以像这样使用它:

container.Resolve<MyClass>(
    new ParameterOverride("myField", new NullInjectionParameterValue<string>()));

答案 1 :(得分:0)

此类行为并非Unity独有 - 大多数DI容器不允许您注入null(除非您手动干预或扩展容器以允许它)。

来自Microsoft's Unity 2.1 documentation(因为Unity 5在Google中没有文档结果):

  

您无法提供null作为要注入的值。您必须显式提供InjectionParameter,与类型一样。

注入服务时,使它们成为null是不合逻辑的。这意味着需要null检查代码遍布整个代码以处理这种情况。相反,我们保护成员变量,使它们永远不会null使代码变得健壮。

public class MyService : IMyService
{
    // Can only be set by the constructor
    private readonly IMyClass myClass;

    public MyService(IMyClass myClass)
    {
        // Can never set to null
        if (myclass == null)
            throw new ArgumentNullException(nameof(myClass));
        this.myClass = myClass;
    }

    public void DoSomething()
    {
        // Null checking is not required here (or anywhere else in
        // this class) because we are guaranteed to have an instance
        // when this object is instantiated.
        // if (this.myClass != null)
        this.myClass.DoSomething();
    }
}

那么当我们想要代表 nothing 时我们该怎么办?使用Null Object Pattern来使用具有 null行为的类来满足IMyClass要求。

public class NullMyClass : IMyClass
{
    public void DoSomething()
    {
        // The logical "null" behavior is to do nothing here
    }
}

现在NullMyClass可与Unity一起使用来表示IMyClass的无操作。

new MyService(null); // Throws NullReferenceException (desired to make the code robust)
new MyService(new MyClass()); // Implements concrete behavior
new MyService(new NullMyClass()) // Implements null behavior (no-op)

unityContainer.Resolve<IMyClass>(new ParameterOverride(myField, new NullMyClass()));

参考:How can I inject a property only if the value is non-null at runtime using Unity?