指定要使用的 Unity IoC 容器的构造函数

Posted

技术标签:

【中文标题】指定要使用的 Unity IoC 容器的构造函数【英文标题】:Specify constructor for the Unity IoC container to use 【发布时间】:2011-01-10 20:21:59 【问题描述】:

我正在使用 Unity IoC 容器来解析我的对象。但是,我遇到了一个问题。当我有多个构造函数时 - Unity 如何知道使用哪一个?当我有一个有参数和一个没有参数时,它似乎使用一个有参数。我可以明确告诉它使用哪个构造函数吗?

具体来说,我有一个类似于以下带有两个构造函数的 Person 类的案例。在这种情况下,我希望 IoC 容器使用默认构造函数 - 不带参数 - 但它会选择带参数的构造函数。

public class SomeValueObject

    public SomeValueObject(string name)
    
        Name = name; 
    
    public string Name  get; set; 


public class Person

    private string _name; 

    public Person()
    
        _name = string.Empty;
    

    public Person(SomeValueObject obj)
    
        _name = obj.Name;
    

这显然失败了,因为它无法创建 SomeValueObject - 不知道向其字符串参数注入什么。它给出的错误是:

解析依赖失败,type = "MyApp.Person", name = ""。异常消息是:当前构建操作(构建密钥 Build Key[MyApp.Person, null])失败:尝试调用构造函数 MyApp.Person(MyApp.SomeValueObject obj) 时无法解析参数 obj。 (策略类型 BuildPlanStrategy,索引 3)

容器注册:

Container.RegisterType<Person, Person>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

解决方法:

var person = Container.Resolve<Person>();

【问题讨论】:

IoC 不就是使用接口吗??? 当然,我主要是这样做的。但这对问题没有影响。 @Martin 许多程序员使用类并避免创建一个接口然后只有一个实现的虚假通用性。它还避免了您在大多数企业应用程序中看到的大量臭气熏天的 IoC 接线,但仍然允许您在需要时切换一些实现。 programmers.stackexchange.com/questions/133471/… 【参考方案1】:

Multiple-Constructor Injection Using an Attribute

当一个目标类包含超过 一个具有相同编号的构造函数 的参数,您必须应用 InjectionConstructor 属性 到 Unity 容器的构造函数 将用于指示哪个构造函数 容器应该使用。与 自动构造函数注入,你 可以指定构造函数参数 作为具体类型,或者您可以指定 接口或基类 Unity 容器包含一个 注册映射。

【讨论】:

【参考方案2】:

默认情况下,Unity 选择具有最大参数数量的构造函数。要覆盖它,请使用 InjectionConstructorAttribute 装饰所需的构造函数。

【讨论】:

我们应该提到,装饰构造函数将组件耦合到 Unity 作为其 IoC 容器。在注册期间处理规范可能更可取,这样组件就不需要引用 Unity,因此可以根据需要换出不同的 IoC。 “默认情况下,Unity 选择具有最大参数数量的构造函数”,但前提是 Unity 知道所有必需的值。就我而言,我错过了注册一种类型,Unity 感觉回到了无参数构造函数。【参考方案3】:

改为这样注册:

container.RegisterType<Person>(new InjectionConstructor());

您也可以使用 RegisterType 方法的重载来添加 LifetimeManager。

也就是说,在为 DI 建模时,如果你有明确的构造函数(即没有重载的构造函数),你的生活会容易得多。

【讨论】:

你指的是哪个重载? @Casey...我相信空的构造函数。 由于 InjectionConstructor 没有参数,所以调用的是 Person 的空构造函数。如果代码是 'new InjectionConstructor(new SomeValueObject("John Smith"))',那将调用(其他)Person 构造函数,其中“其他”构造函数是使用 SomeValueObject 对象/参数的构造函数。跨度> 如果您不想为类的依赖项传入手动对象,而是希望 Unity 注入您已经注册的类型,也可以使用 new InjectionConstructor(typeof(IMyDependency), typeof(IMySecondDependency)) 指定具有依赖项的构造函数class="comcopy">跨度> 看起来您甚至不必这样做。您可以将Unity.Attributes.InjectionConstructorAttribute 放在您的构造函数上! - 感谢您为我指明正确的方向! :)【参考方案4】:

我真的必须指出你在这种情况下使用依赖注入的方式是错误的。容器应该能够在构造上注入 SomeValueObject。

您最可能应该做的是注册 SomeValueObject 的默认对象,该对象的 .Name 属性返回 string.Empty

【讨论】:

也许我的简单示例有点不对劲,但 imo 在实际代码中需要两个不同的构造函数。无论如何感谢您的提及。 没写怎么办?

以上是关于指定要使用的 Unity IoC 容器的构造函数的主要内容,如果未能解决你的问题,请参考以下文章

(VIP-朝夕教育)2021-06-05 .NET高级班 37-Unity容器的使用

容器Unity实现IOC+DI

IOC小结

使用 IoC 容器时,原始构造函数参数是否一个坏主意? [关闭]

一步一步造个IoC轮子:构造基本的IoC容器

IoC.Resolve 与构造函数注入