Dependency Injection Framework Castle Windsor parse an instance from a container (that is, call the Resolve method), by invoking the constructor of the object to be parsed and returning it, the question is: which constructor does it call?
- Non-parametric constructors
- A constructor with parameters that are not dependent on injection
- parameter is a constructor that relies on injection
- A constructor that has multiple parameters and is dependent on injection
With this problem, I wrote a test code.
Test 1:
There is only one parameterless constructor:
Ctortest Class (Use Windsor to parse this class in a console program)
Public class ctortest { publicstringgetset;} Public ctortest () { = $"Themessage is from {nameof (ctortest)}"; } Public void showmessage () { Console.WriteLine (Message); } }
The console main code looks like this:
class program { staticvoid Main (string[] args) { new WindsorContainer (); Ioccontainer.register (component.for<CtorTest> (). Implementedby<ctortest>(). Lifestylesingleton ()); var instance = ioccontainer.resolve<ctortest>(); Instance. ShowMessage (); } }
Test results (the default constructor is the same as the non-parametric constructor property):
Test 2
There is only one constructor with a parameter but not a dependency injection (no parameterless constructor)
The Ctortest code is as follows:
Public string Get Set ; } Public Ctortest (string message) { = $"Themessage is from {nameof ( ctortest)}"; } Public void showmessage () { Console.WriteLine (Message); } }
The test result, of course, throws an exception:
If you provide a default value for this parameter (for example, String message= ""), resolve will call this constructor, and if you add an parameterless constructor, resolve will invoke the parameter, such as adding a parameter constructor with two default values, which will call two arguments. So here's the conclusion: there is a parameter with The default value first (the number of arguments first), and then no parameter .
Test 3:
There is a constructor with parameters that is dependent on injection, and a parameterless constructor, and two constructors with default value parameters.
Add a Sub class:
Public class Sub { publicstringgetset;} Public Sub () { = $"Themessage is from {nameof (Sub)}"; } }
The ctor class code is as follows:
Public class ctortest { publicstringgetset;} Public ctortest () { = $"Themessage is from {nameof (ctortest)}"; }
Public Ctortest (String message = "Message1", String message2= "Message2")
{
Message = $ "The message is from {nameof (ctortest)} and {message} and {message2}";
}
Public Ctortest (sub sub) { = Sub. Message; } Public Ctortest (string"") { = $"Themessage is from {nameof ( ctortest)}"; } Public void showmessage () { Console.WriteLine (Message); } }
Main is as follows:
classProgram {Static voidMain (string[] args) {IWindsorContainer Ioccontainer=NewWindsorContainer (); Ioccontainer.register (Component.for<CtorTest> (). Implementedby<ctortest>(). Lifestylesingleton ());
// inject Sub into container ioccontainer.register (component.for<sub> (). Implementedby<sub>(). Lifestylesingleton ()); varInstance = ioccontainer.resolve<ctortest>(); Instance. ShowMessage (); } }
Test results:
As you can see from the results , you create an instance by using a constructor with a parameter that is a dependency injection, even if you have a constructor that has 2 parameters with a default value .
Test 4
Two parameters that are dependent on the injected constructor
Add a SUB2 class:
Public class SUB2 { publicstringgetset;} Public Sub2 () { = $"Themessage is from {nameof (SUB2)}"; } }
The ctor class code is as follows:
Public classCtortest { Public stringMessage {Get;Set; } Publicctortest () {Message= $"The message is from {nameof (ctortest)}"; } // Note: I deliberately put this in front of the sub parameter's constructor Public ctortest (Sub2 sub2) {Message = sub2. Message; } Public Ctortest (sub sub) {Message = Sub. Message; } PublicCtortest (stringMessage ="") {Message= $"The message is from {nameof (ctortest)}"; } Public voidShowMessage () {Console.WriteLine (Message); } }
The main class code is as follows:
classProgram {Static voidMain (string[] args) {IWindsorContainer Ioccontainer=NewWindsorContainer (); Ioccontainer.register (Component.for<CtorTest> (). Implementedby<ctortest>(). Lifestylesingleton ());
//inject the sub2 into the container, and notice I deliberately put sub2 in front of the sub.Ioccontainer.register (Component.for<sub2> (). Implementedby<sub2>(). Lifestylesingleton ()); //inject the sub into the containerIoccontainer.register (Component.for<sub> (). Implementedby<sub>(). Lifestylesingleton ()); varInstance = ioccontainer.resolve<ctortest>(); Instance. ShowMessage (); } }
Test results:
Although I put Sub2 's constructor and registration in front of the sub, I finally called the constructor with the sub parameter. So what's the order of it? by modifying the name of the class (for example, by changing the SUB2 to the name in front of the sub, such as S, the constructor of the s parameter is called)
Test 5
There are two constructors with parameters that are dependent on injection
Put the ctortest in the class.
Public ctortest (Sub2 sub2) { = sub2. Message; }
Modified into
Public ctortest (Sub2 sub2,sub Sub) { = sub2. Message +environment.newline + Sub. Message; }
Test results:
It calls the modified constructor, which means that it first calls the one with the most arguments.
Final total:
Resolve the number of arguments and arguments through dependency injection constructors, if there are more than one constructor with the same number of arguments, the first is called by the parameter type name (the name should be the fully qualified name, no test), and if there is no such constructor, A constructor that has a number of arguments and has a default value is called first.
Discussion on the new object in the analysis of the Resolve method of Castle Windsor