Unity.Resolve 如何知道使用哪个构造函数?

Posted

技术标签:

【中文标题】Unity.Resolve 如何知道使用哪个构造函数?【英文标题】:How does Unity.Resolve know which constructor to use? 【发布时间】:2011-01-29 00:45:28 【问题描述】:

给定一个具有多个构造函数的类 - 我如何告诉 Resolve 使用哪个构造函数?

考虑以下示例类:

public class Foo

    public Foo()  
    public Foo(IBar bar)
    
        Bar = bar;
    
    public Foo(string name, IBar bar)
    
        Bar = bar;
        Name = name;
    
    public IBar Bar  get; set;         
    public string Name  get; set; 

如果我想使用 Resolve 创建一个 Foo 类型的对象,Resolve 如何知道要使用哪个构造函数?我怎么能告诉它使用正确的呢?假设我有一个注册了 IBar 的容器 - 它会理解它应该支持使用 IBar 的构造函数吗?如果我也指定一个字符串 - 它会使用(string, IBar) 构造函数吗?

Foo foo = unityContainer.Resolve<Foo>(); 

并且请忽略这样一个事实,如果该类只有一个构造函数可能会更容易......

【问题讨论】:

【参考方案1】:

当一个目标类包含多个构造函数时,Unity 将使用应用了 InjectionConstructor 属性的那个。如果有多个构造函数,并且没有一个带有 InjectionConstructor 属性,Unity 将使用参数最多的构造函数。如果有多个这样的构造函数(多个参数相同的“最长”构造函数),Unity 将引发异常。

取自link text

【讨论】:

正是我想要的!我只是装饰了我想用 [InjectionConstructor] 使用的构造函数 这就是可以节省一个周末的答案。定义明确。 我遇到过Unity没有选择参数最多的构造函数的情况。构造函数有两种,一种有1个参数,另一种有4个参数。它选择一个参数,这是为什么呢?有什么想法或想法,或者我应该在哪里检查?【参考方案2】:

当你注册类型时,你可以像这样指定使用哪个构造函数:

container.RegisterType<Foo>(
    new InjectionConstructor(
        new ResolvedParameter<IBar>()));

以上代码来自记忆,但这是一般原则。在本例中,我选择了采用 IBar 类型的单个参数的构造函数。

请忽略这样一个事实,如果该类只有一个构造函数可能会更容易......

我不能忽视这一点。当谈到构造函数注入时,歧义是一种设计味道。你基本上是在说:我真的不知道我是否关心这种依赖关系。

当然,Unity 可能会为您解决问题,但是您将依赖特定的容器行为,而不是正确设计您的 API。 其他容器可能有不同的行为,因此如果您选择从 Unity 迁移到更好的容器,可能会出现细微的错误。

以DI-friendly, but container-agnostic 方式编写代码更安全。

【讨论】:

谢谢!但是我真的需要在容器中注册类型吗?我将使用容器来解析 Foo 的实例,但我不需要 Foo 在容器中。但是我仍然应该使用RegisterType?或者只是因为我有这种特殊需要告诉它使用哪个构造函数? 是的,也不是。正如 ozczecho 所引用的那样,Unity 使用启发式方法来面对歧义来选择构造函数(它会选择具有最多参数的构造函数)。如果你需要它偏离这个算法,你必须明确告诉它。一种方法是应用 InjectionConstructor 属性,另一种方法是在容器中注册它。我个人更喜欢在容器中注册类型,因为这让我的代码与容器无关。如果适用,它还允许不同的容器配置。 FWIW,Unity 解析具体类型(即使它们尚未在容器中注册)的能力是它特有的功能。一些容器支持该功能,而另一些则不支持。 +1 你是对的,指出歧义是一种设计气味,让我意识到我应该使用参数注入而不是构造函数注入。我尝试两个构造函数的唯一原因是为了可测试性。

以上是关于Unity.Resolve 如何知道使用哪个构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在priority_queue中使用函子作为自定义比较器

是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]

Kotlin:子构造函数如何使用其父构造函数的辅助构造函数?

JAVA中构造方法和普通方法的区别

Ninject - 如何在构造过程中识别哪个类抛出异常

在ORACLE中获得某个字元在一个字串中位置是哪个函式