对Castle Windsor的Resolve方法的解析时new对象的探讨

依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢?

  • 无参的构造函数
  • 带参但参数不是靠依赖注入的构造函数
  • 带参且参数是靠依赖注入的构造函数
  • 有多个带参且参数是靠依赖注入的构造函数

带着这个问题,我写了一段测试代码.

测试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会调用带参的,如再加一个带有两个带默认值的带参构造函数,则会调用两个参数的,所以这里的结论是:带有默认值的有参(先参数个数多的),再无参.

测试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先调用参数个数多且参数通过依赖注入的构造函数,如果参数个数相同的构造函数有多个,则按参数类型名称(这个名称应该是完全限定名,没有测试)顺序,调用第一个,如果不存在这样的构造函数,则优先调用参数个数多且具有默认值的构造函数.

时间: 2024-10-14 05:32:16

对Castle Windsor的Resolve方法的解析时new对象的探讨的相关文章

在ABP项目的应用Castle Windsor

Castle Windsor常用介绍以及其在ABP项目的应用介绍 最近在研究ABP项目,有关ABP的介绍请看阳光铭睿 博客,ABP的DI和AOP框架用的是Castle Windsor下面就对Castle Windsor项目常用方法介绍和关于ABP的使用总结 1.下载Castle.Windsor所需要的dll,在程序包管理器控制台 运行Install-Package Castle.Windsor 下面先看个简单的例子 1 2 3 4 5 6 7 8 var container = new Wind

Castle Windsor常用介绍以及其在ABP项目的应用介绍

最近在研究ABP项目,有关ABP的介绍请看阳光铭睿 博客,ABP的DI和AOP框架用的是Castle Windsor下面就对Castle Windsor项目常用方法介绍和关于ABP的使用总结 1.下载Castle.Windsor所需要的dll,在程序包管理器控制台 运行Install-Package Castle.Windsor 下面先看个简单的例子 var container = new WindsorContainer(); container.Register( Component.For

ASP.NET Web API - 使用 Castle Windsor 依赖注入

示例代码 项目启动时,创建依赖注入容器 定义一静态容器 IWindsorContainer 1 private static IWindsorContainer _container; 在 Application_Start() 中,创建该容器 1 _container = new WindsorContainer(); 调用 Container Install 方法,向容器内注册组件 1 _container.Install(FromAssembly.This()); 该语句会调用整个程序集中

Castle.Windsor依赖注入的高级应用_Castle.Windsor.3.1.0

[转]Castle.Windsor依赖注入的高级应用_Castle.Windsor.3.1.0 1. 使用代码方式进行组件注册[依赖服务类] using System; using System.Collections.Generic; using System.Linq; using System.Text; using CastleDemo.Lib; using Castle.Windsor; using Castle.Windsor.Configuration.Interpreters;

Castle.Windsor IOC/AOP的使用

Castle最早在2003年诞生于Apache Avalon项目,目的是为了创建一个IOC(控制反转)框架.发展到现在已经有4个组件了,分别是ActiveRecord(ORM组件).Windsor(IOC组件).DynamicProxy(动态代理组件).MonoRail(Web MVC组件). 这里我们要学习的是Windsor组件,Windsor是Castle提供的一个IOC框架. 使用之前,首先需要引用两个DLL,分别是:Castle.Core 和 Castle.Windsor. IOC(控制

在ASP.NET MVC中使用Castle Windsor

平常用Inject比较多,今天接触到了Castle Windsor.本篇就来体验其在ASP.NET MVC中的应用过程. Visual Studio 2012创建一个ASP.NET MVC 4网站. 通过NuGet安装Castle Windsor. 在当前项目下创建一个名称为"IOC"的文件夹. 在ASP.NET MVC中,每次请求,DefaultControllerFactory都会为我们创建controller实例,我们需要自定义一个派生自DefaultControllerFact

c# Castle Windsor简单例子

Windsor是Castle的IOC框架.需要用到两个dll(Castle.Core.dll和Castle.Windsor.dll). 1.接口以及接口实现类: public interface ITest { int Add(int a, int b); } public class Test:ITest { public int Add(int a, int b) { return a + b; } } 2.创建自定义类WindsorInstaller,继承IWindsorInstaller

Castle.Windsor依赖注入的高级应用

1. 使用代码方式进行组件注册[依赖服务类] using System; using System.Collections.Generic; using System.Linq; using System.Text; using CastleDemo.Lib; using Castle.Windsor; using Castle.Windsor.Configuration.Interpreters; using Castle.MicroKernel.Registration; namespace

Castle Windsor 学习-----Installer的几种安装方式

翻译 当使用依赖注入容器时,你首先要向容器中注册你的组件,Windsor使用installers(该类型实现IWindsorInstaller接口)来封装和隔离注册的逻辑,可以使用Configuration和FromAssembly来完成工作. Installers是实现了IWindsorInstaller接口的简单类型,只有一个Install方法,该方法接收container参数,该参数使用 fluent registration API方式来注册组件 public class Reposit