Unity not using the default constructor of the class
Asked Answered
S

3

22

I have this class :

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

    {

    }

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

}

I added a line to web.config so that this type will be automatically constructed by Unity container.

but during the execution of my application, I receive this error message :

  "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) Why isn't Unity using the default constructor ?

2) Suppose I want Unity to use the second constructor (the parametized one), How do I pass that information to Unity via the configuration file ?

Smallsword answered 9/3, 2011 at 22:38 Comment(0)
S
58

Unity by default picks the constructor with the most parameters. You have to tell Unity to use a different one explicitly.

One way to do this is with the [InjectionConstructor] attribute like this:

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.
   }
}

A second way of doing this, if your opposed to cluttering up classes/methods with attributes, is to specify which constructor to use when configuring your container using an InjectionConstructor:

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

From the documentation:

How Unity Resolves Target Constructors and Parameters

When a target class contains more than one constructor, Unity will use the one that has the InjectionConstructor attribute applied. If there is more than one constructor, and none carries the InjectionConstructor attribute, Unity will use the constructor with the most parameters. If there is more than one such constructor (more than one of the "longest" with the same number of parameters), Unity will raise an exception.

Stadtholder answered 9/3, 2011 at 22:40 Comment(5)
@IanWarburton If you explain what you tried, and what you saw, i will try to help you resolve the issue.Stadtholder
Hmm good to know! Somehow I expected it to call the constructor with the LEAST parameters... interestingPeople
Why doesn't Unity pick the default constructor as its default? Doesn't make much sense too me...Bernhardt
@Bernhardt this is only me guessing at the intent of picking the constructor with the most arguments, based on the When to Use Constructor Injection section of the documentation. One point they make is that people use constructor parameters to clearly indicate the dependencies of the class are. Another reason to prefer the one with the most arguments is that people may need to initialize them at construction because the field will not have a property or method made for it.Stadtholder
Seems to me as a ridiculous decision to use a constructor with the most arguments. I encountered an issue when a third party library class I used was extended with an additional constructor, I updated the library and, bam, my code is broken.Instanter
S
23

Just try to register type this way:

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

Because of no param element specified in constructor element it should call default constructor.

You can also do this registration in code:

container.RegisterType<IRepo, Repo>(new InjectionConstructor());
Spermaceti answered 9/3, 2011 at 22:58 Comment(1)
Best answer! This solves the issue, previous comment just explains the default behavior.Nkvd
P
0

I had a more simple problem that resulted in this error.

The container that I was using was the wrong container. I had accidentally created two different containers and my container.RegisterType<Interface,ConcreteObject> was inside of another container from the one being used.

Plaudit answered 10/7, 2020 at 21:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.