對Castle Windsor的Resolve方法的解析時new對象的探討

依賴注入框架Castle Windsor從容器裏解析一個實例時(也就是調用Resolve方法),是經過調用待解析對象的構造函數new一個對象並返回,那麼問題是:它是調用哪一個構造函數呢?框架

  • 無參的構造函數
  • 帶參但參數不是靠依賴注入的構造函數
  • 帶參且參數是靠依賴注入的構造函數
  • 有多個帶參且參數是靠依賴注入的構造函數

帶着這個問題,我寫了一段測試代碼.函數

 

測試1:測試

只有一個無參構造函數:spa

CtorTest類(在控制檯程序裏用Windsor解析這個類)3d

   public class CtorTest
    {

       public string Message { get; set; }

        public CtorTest()
        {
            Message = $"The message is from {nameof(CtorTest)}";
        }

        public void ShowMessage()
        {
            Console.WriteLine(Message);
        }
    }

控制檯Main代碼以下所示:code

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();
        }
    }

測試結果(默認構造函數與無參構造函數性質是同樣的):對象

 

測試2blog

只有一個帶參但不是靠依賴注入的構造函數(沒有無參數構造函數)排序

CtorTest代碼以下:get

 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先調用參數個數多且參數經過依賴注入的構造函數,若是參數個數相同的構造函數有多個,則按參數類型名稱(這個名稱應該是徹底限定名,沒有測試)順序,調用第一個,若是不存在這樣的構造函數,則優先調用參數個數多且具備默認值的構造函數.

相關文章
相關標籤/搜索