Unity没有使用类的默认构造函数

22

我有这个类:

public class Repo
{
   public Repo() : this(ConfigurationManager.AppSettings["identity"],       ConfigurationManager.AppSettings["password"])

    {

    }

   public Repo(string identity,string password)
   {
       //Initialize properties.
   }

}

我向web.config文件中添加了一行代码,以便让Unity容器自动构建该类型。

但在我的应用程序执行过程中,我收到了以下错误信息:

  "System.InvalidOperationException : the parameter identity could not be resolved when attempting to call constructor Repo(String identity, String password)  -->Microsoft.Practices.ObjectBuilder2.BuildFailedException : The current Build operation ...."

1) 为什么Unity没有使用默认构造函数?

2) 假设我想让Unity使用第二个构造函数(带参数的构造函数),我该如何通过配置文件将这些信息传递给Unity?

3个回答

58

默认情况下,Unity会选择具有最多参数的构造函数。你需要明确告诉Unity使用不同的构造函数。

一种方法是使用 [InjectionConstructor] 属性,像这样:

using Microsoft.Practices.Unity;

public class Repo
{
   [InjectionConstructor]
   public Repo() : this(ConfigurationManager.AppSettings["identity"], ConfigurationManager.AppSettings["password"])
   {

   }

   public Repo(string identity,string password)
   {
       //Initialize properties.
   }
}

如果你不想在类/方法中添加属性来实现这个,第二种方法是在配置容器时指定要使用哪个构造函数,使用InjectionConstructor:

IUnityContainer container = new UnityContainer();
container.RegisterType<Repo>(new InjectionConstructor());

根据文档

Unity如何解析目标构造函数和参数

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


@IanWarburton 如果你解释一下你尝试了什么,看到了什么,我会尽力帮助你解决这个问题。 - Steven Magana-Zook
1
好的,知道了!不知怎么的,我以为它会调用最少参数的构造函数...有趣。 - Jowen
为什么Unity不选择默认构造函数作为其默认值?对我来说没有太多意义... - talles
1
@talles 这只是我根据文档中的“何时使用构造函数注入”部分猜测选择具有最多参数的构造函数的意图。他们提到的一个要点是人们使用构造函数参数来清楚地指示类的依赖关系。另一个偏爱具有最多参数的原因是人们可能需要在构造过程中初始化它们,因为该字段将没有为其创建属性或方法。 - Steven Magana-Zook
对我来说,使用最多参数的构造函数似乎是一个荒谬的决定。 当我使用的第三方库类被扩展了一个额外的构造函数时,我遇到了一个问题,我更新了库,结果我的代码就崩溃了。 - Mykhailo Seniutovych

23

尝试以这种方式注册类型:

<register type="IRepo" mapTo="Repo">
  <constructor />
</register>

由于constructor 元素中没有指定 param 元素,因此应该调用默认构造函数。

你也可以在代码中进行这种注册:

container.RegisterType<IRepo, Repo>(new InjectionConstructor());

1
最佳答案!这解决了问题,之前的评论只是解释了默认行为。 - charino

0

我遇到了一个更简单的问题,导致了这个错误。

我使用的容器错误的容器。我不小心创建了两个不同的容器,而我的container.RegisterType<Interface,ConcreteObject>在另一个容器中而不是正在使用的那个容器中。


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