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

44
我正在使用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 - 不知道要注入哪个字符串参数。 它给出的错误是:

依赖项的解析失败,类型 =“MyApp.Person”,名称 =“”。 异常消息是:当前构建操作(构建键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>();

依赖注入的重点不是使用接口吗? - Martin
5
当然,我大多数时候都这样做。但这对问题没有影响。 - stiank81
@Martin 许多程序员使用类,避免制作接口然后只有一个实现的虚假普遍性。这也避免了大量臭气熏天的IoC连接,在大多数企业应用程序中可以看到,但仍然可以在需要时切换一些实现。http://programmers.stackexchange.com/questions/133471/writing-testable-code-vs-avoiding-speculative-generality - Luke Puplett
4个回答

51

改为以下方式进行注册:

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

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

话虽如此,当用于DI时,如果你拥有明确的构造函数(即没有重载的构造函数),你的生活会更加轻松。


1
你指的是哪个重载? - Casey
@Casey...我相信是空构造函数。 - granadaCoder
由于InjectionConstructor没有参数,它正在调用Person的空构造函数。如果代码是'new InjectionConstructor(new SomeValueObject("John Smith"))',那么将调用(另一个)Person构造函数,其中“其他”构造函数是使用SomeValueObject对象/参数的构造函数。 - granadaCoder
2
如果您不想为类的依赖项传递手动对象,而是希望Unity注入已注册的类型,则可以使用new InjectionConstructor(typeof(IMyDependency), typeof(IMySecondDependency))来指定具有依赖项的构造函数。 - Seafish
看起来你甚至不需要这样做。你只需要在构造函数上放置Unity.Attributes.InjectionConstructorAttribute即可!--感谢您指引我正确的方向! :) - BrainSlugs83

28

默认情况下,Unity会选择参数最多的构造函数。要更改这种行为,请用InjectionConstructorAttribute修饰所需的构造函数。


7
我们应该提到,装饰构造函数将组件与Unity作为其IoC容器相结合。在注册期间处理规范可能更可取,这样组件就不需要引用Unity,如果需要,可以切换到不同的IoC。 - Sean B
默认情况下,Unity会选择具有最大参数数量的构造函数,但前提是所有必需的值对于Unity来说都是已知的。在我的情况下,我错过了注册一个类型,因此Unity退回到了一个无参构造函数。 - royalTS

4

使用属性进行多构造函数注入

当目标类包含具有相同参数数量的多个构造函数时,您必须将InjectionConstructor属性应用于Unity容器将用于指示容器应使用哪个构造函数的构造函数。与自动构造函数注入一样,您可以将构造函数参数指定为具体类型,也可以指定Unity容器包含已注册映射的接口或基类。


-3

我必须指出,你在这个实例中使用依赖注入的方式是错误的。容器应该能够在构造时注入SomeValueObject。

你最可能要做的是注册一个默认的SomeValueObject对象,使其.Name属性返回string.Empty


也许我的简单示例有点偏差,但在我看来,实际代码中需要两个不同的构造函数。无论如何,感谢提及。 - stiank81
如果你没有写过它呢? - Casey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接