繁体   English   中英

使用Unity容器的DI - 使用其他参数解决的最佳实践?

[英]DI with Unity Container - Best practices resolving with additional parameters?

例:

IApple和实施Apple Apple构造函数:

public Apple(IVitamin vitamin, int size)

我可以注册所有DI和IApple:

container.RegisterType<IApple,Apple>();
container.RegisterInstance<IVitamin>(vitamin);

我现在可以在创建apple实例时覆盖参数以插入int size参数:

var apple = container.Resolve<IApple>(new ParameterOverrides<Apple> {{"size", 9001}}

你必须在那里写入参数的字符串(“大小”)似乎很麻烦。 当涉及其他参数时,这是否是首选DI? 或者我是否必须创建一个处理该工作的AppleFactory(或者通常是工厂)? (对于具有非DI属性以及DI属性的每个类,必须编写工厂似乎有点过头了。

或者你不应该手动覆盖和设置属性?

var apple = container.Resolve<IApple>();
apple.Size = 9001;

这样,代码逻辑将从构造函数传递到属性的setter。

你必须在那里写参数的字符串(“大小”)似乎很麻烦

是的,这很难看,但是没有办法绕过它,至少不是Unity。

为每个具有非DI属性和DI属性的类编写工厂似乎有点过分

没错,但这可能是你应该做的。 您的大多数代码不应直接依赖于容器。

如果你创建一个工厂,参数覆盖不是那么难看,因为你可以使用nameof而不是字符串:

class AppleFactory : IAppleFactory
{
    ...

    public IApple CreateApple(int size)
    {
        return _container.Resolve<IApple>(new ParameterOverrides<Apple> {{nameof(size), size}};
    }
}

另一种方法是使用我的Unity.Extras.AutoFactory扩展,但请记住它处于alpha状态...

我建议想为什么你会以这种方式将一个integer注入到类中。 如果每个使用unity实例化的Apple都会注入相同的值,那么值是否为常数? 如果是的话,你真的不需要注入它。 它可以只是Apple一部分。 但是在你的例子中,如果Apple代表一个实体或具有状态的对象并且可以具有不同的大小,那么Factory绝对是一个更好的选择。 Factory将在初始化期间设置属性值。 如果您正在测试代码,那么您将自己帮忙将这些决策转移到Factory ,并使IoC容器配置专注于构建依赖树而不是处理初始对象状态的值。

我认为你的例子太简单了。 如果你要创建不同大小的苹果,你可能不会从容器中解决它们(你通过容器创建苹果的方式有点奇怪,它看起来更适合factory然后container ) 。

不要忘记容器的主要用途是连接复杂的对象组合/依赖项,这些组合/依赖项应该能够从容器的当前状态创建。 当您发现自己为Resolve方法提供参数时,我认为您应该停止并尝试避免它,可能需要重新设计,重构是正确的方向。

附注

在大多数情况下,当我需要注入原语时,我会使用类似这样的struct / class

public struct AppleSize {
     public int Value { get; }
     .....
}

现在我可以在container注册AppleSize实例,Apple构造函数将使用AppleSize而不是int 避免注册原语。 更好地使用更具描述性的结构/类定义。

如果场景更复杂 (要注入的原语可能依赖于太多的参数并需要计算/操作),那么我将创建factory封装与对象创建相关的任何操作 ,这更接近您的场景我认为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM