对Castle Windsor的Resolve方法的解析时new对象的探讨
2017-01-03 21:49
453 查看
依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢?
无参的构造函数
带参但参数不是靠依赖注入的构造函数
带参且参数是靠依赖注入的构造函数
有多个带参且参数是靠依赖注入的构造函数
带着这个问题,我写了一段测试代码.
测试1:
只有一个无参构造函数:
CtorTest类(在控制台程序里用Windsor解析这个类)
控制台Main代码如下所示:
测试结果(默认构造函数与无参构造函数性质是一样的):
测试2
只有一个带参但不是靠依赖注入的构造函数(没有无参数构造函数)
CtorTest代码如下:
测试结果,当然是抛出异常:
如果为这个参数提供默认值(如:string message=""),Resolve会调用这个构造函数,如果再加一个无参构造函数,Resolve会调用带参的,如再加一个带有两个带默认值的带参构造函数,则会调用两个参数的,所以这里的结论是:先[b]带有默认值的有参(先参数个数多的),再无参.[/b]
测试3:
有一个带参且参数是靠依赖注入的构造函数,和一个无参数构造函数,一个两个具有默认值参数的构造函数.
添加一个Sub类:
Ctor类代码如下:
public CtorTest(string message = "message1",string message2= "message2")
{
Message = $"The message is from {nameof(CtorTest)} and {message} and {message2}" ;
}
Main如下:
测试结果:
从结果可以看出它是通过带参(参数是依赖注入)的构造函数创建实例,即使在有一个2个具有默认值的参数的构造函数的情况下.
测试4
两个带参且参数是靠依赖注入的构造函数
添加一个Sub2类:
Ctor类代码如下:
Main类代码如下:
测试结果:
尽管我把Sub2的构造函数和注册都放在了Sub前面,但最终还是调用了带Sub参数的构造函数.那么它的顺序是什么呢?通过修改类的名称(比如说把Sub2改成排序在Sub前的名称,如S,那么就会调用S这个参数的构造函数)
测试5
有两个带参且参数是靠依赖注入的构造函数
把CtorTest类里的
修改成
测试结果:
它调用的是修改后的这个构造函数,也就是说:它先调用了参数多的那个.
最终总终:
Resolve先调用参数个数多且参数通过依赖注入的构造函数,如果[b]参数个数相同的构造函数有多个,则按参数类型名称(这个名称应该是完全限定名,没有测试)顺序,调用第一个,如果不存在这样的构造函数,则优先调用参数个数多且具有默认值的构造函数.[/b]
无参的构造函数
带参但参数不是靠依赖注入的构造函数
带参且参数是靠依赖注入的构造函数
有多个带参且参数是靠依赖注入的构造函数
带着这个问题,我写了一段测试代码.
测试1:
只有一个无参构造函数:
CtorTest类(在控制台程序里用Windsor解析这个类)
public class CtorTest { public string Message { get; set; } public CtorTest() { Message = $"The message is from {nameof(CtorTest)}"; } public void ShowMessage() { Console.WriteLine(Message); } }
控制台Main代码如下所示:
class Program { static void Main(string[] args) { IWindsorContainer iocContainer = new WindsorContainer(); iocContainer.Register(Component.For<CtorTest>().ImplementedBy<CtorTest>().LifestyleSingleton()); var instance = iocContainer.Resolve<CtorTest>(); instance.ShowMessage(); } }
测试结果(默认构造函数与无参构造函数性质是一样的):
测试2
只有一个带参但不是靠依赖注入的构造函数(没有无参数构造函数)
CtorTest代码如下:
public string Message { get; set; } public CtorTest(string message) { Message = $"The message is from {nameof(CtorTest)}"; } public void ShowMessage() { Console.WriteLine(Message); } }
测试结果,当然是抛出异常:
如果为这个参数提供默认值(如:string message=""),Resolve会调用这个构造函数,如果再加一个无参构造函数,Resolve会调用带参的,如再加一个带有两个带默认值的带参构造函数,则会调用两个参数的,所以这里的结论是:先[b]带有默认值的有参(先参数个数多的),再无参.[/b]
测试3:
有一个带参且参数是靠依赖注入的构造函数,和一个无参数构造函数,一个两个具有默认值参数的构造函数.
添加一个Sub类:
public class Sub { public string Message { get; set; } public Sub() { Message = $"The message is from {nameof(Sub)}"; } }
Ctor类代码如下:
public class CtorTest { public string Message { get; set; } public CtorTest() { Message = $"The message 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) { Message = sub.Message; } public CtorTest(string message = "") { Message = $"The message is from {nameof(CtorTest)}"; } public void ShowMessage() { Console.WriteLine(Message); } }
Main如下:
class Program { static void Main(string[] args) { IWindsorContainer iocContainer = new WindsorContainer(); iocContainer.Register(Component.For<CtorTest>().ImplementedBy<CtorTest>().LifestyleSingleton()); //把sub注入到容器中 iocContainer.Register(Component.For<Sub>().ImplementedBy<Sub>().LifestyleSingleton()); var instance = iocContainer.Resolve<CtorTest>(); instance.ShowMessage(); } }
测试结果:
从结果可以看出它是通过带参(参数是依赖注入)的构造函数创建实例,即使在有一个2个具有默认值的参数的构造函数的情况下.
测试4
两个带参且参数是靠依赖注入的构造函数
添加一个Sub2类:
public class Sub2 { public string Message { get; set; } public Sub2() { Message = $"The message is from {nameof(Sub2)}"; } }
Ctor类代码如下:
public class CtorTest { public string Message { get; set; } public CtorTest() { Message = $"The message is from {nameof(CtorTest)}"; }//注意:我故意把这个放到sub参数的构造函数前面
public CtorTest(Sub2 sub2)
{
Message = sub2.Message;
}
public CtorTest(Sub sub)
{
Message = sub.Message;
}
public CtorTest(string message = "")
{
Message = $"The message is from {nameof(CtorTest)}";
}
public void ShowMessage()
{
Console.WriteLine(Message);
}
}
Main类代码如下:
class Program { static void Main(string[] args) { IWindsorContainer iocContainer = new WindsorContainer(); iocContainer.Register(Component.For<CtorTest>().ImplementedBy<CtorTest>().LifestyleSingleton()); //把sub2注入到容器中,注意我故意把sub2放到sub前面 iocContainer.Register(Component.For<Sub2>().ImplementedBy<Sub2>().LifestyleSingleton()); //把sub注入到容器中 iocContainer.Register(Component.For<Sub>().ImplementedBy<Sub>().LifestyleSingleton()); var instance = iocContainer.Resolve<CtorTest>(); instance.ShowMessage(); } }
测试结果:
尽管我把Sub2的构造函数和注册都放在了Sub前面,但最终还是调用了带Sub参数的构造函数.那么它的顺序是什么呢?通过修改类的名称(比如说把Sub2改成排序在Sub前的名称,如S,那么就会调用S这个参数的构造函数)
测试5
有两个带参且参数是靠依赖注入的构造函数
把CtorTest类里的
public CtorTest(Sub2 sub2) { Message = sub2.Message; }
修改成
public CtorTest(Sub2 sub2,Sub sub) { Message = sub2.Message +Environment.NewLine + sub.Message; }
测试结果:
它调用的是修改后的这个构造函数,也就是说:它先调用了参数多的那个.
最终总终:
Resolve先调用参数个数多且参数通过依赖注入的构造函数,如果[b]参数个数相同的构造函数有多个,则按参数类型名称(这个名称应该是完全限定名,没有测试)顺序,调用第一个,如果不存在这样的构造函数,则优先调用参数个数多且具有默认值的构造函数.[/b]
相关文章推荐
- 获得数据库对象的方法探讨(2)
- 使用JSON做Ajax解析服务端返回的JSON对象方法
- Objective-C开发——类、对象和方法解析
- 参照jQuery.ajax改造tangram的baidu.url.jsonToQuery()方法使之支持json嵌套对象的解析
- new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系
- TDD Tip:方法内部New出来的对象如何Mock
- String s=new String("xyz") 创建了几个对象(详细解析)
- 跟踪由new创建的对象的所未释放的内存资源的方法
- java spring、.net castle windsor 、unity容器使用方法对比
- 手工方法使用dcom对象时,编译出错,无法解析的外部符号 _CLSID_...
- TDD Tip:方法内部New出来的对象如何Mock
- 关于Java中Scanner对象的hasNext()方法对实现Readable接口的对象中的read()方法调用的探讨
- 两个解析字符串的方法(new)
- Hibernate几个易混淆方法解析及对象状态解析
- [对象和类型]8.C#构造函数,怎样用静态方法解决私有构造函数造成的不能new的问题?
- Jquery.ajax不能解析json对象,报Invalid JSON错误的原因和解决方法(转)
- javascript 解析后的xml对象的读取方法细解
- Jquery.ajax不能解析json对象,报Invalid JSON错误的原因和解决方法
- QTP之reporter对象方法全解析
- 一道面试题:解析方法中对象存放以及堆栈之间的关系