從容器中的可用服務中, 選取一個構造函數來創造對象, 這個過程就是自動裝配.
一、選擇構造函數
默認情況下, autofac會使用無參構造函數, 去創建對象. 我將Person類稍微修改了下.
public interface IPerson { void Self(); } public class Person : IPerson { IAnimal adopt; public string Name { get; set; } public int Age { get; set; } public Person() { Console.WriteLine("無參構造函數"); } public Person(IAnimal MyPerson) { Console.WriteLine("一個參數構造函數"); adopt = MyPerson; } public Person(string name, int age) { Console.WriteLine("兩個參數構造函數"); this.Name = name; this.Age = age; } public void Self() { Console.WriteLine("我叫{0}, 今年{1}歲了!", this.Name, this.Age); } public void Say() { Console.WriteLine("我領養了一只小動物"); adopt.Say(); } }
但是也可以通過傳入參數的方式, 去自動選擇使用哪一個構造函數. 還可以在注冊的時候就指定使用哪一個構造函數.
builder.RegisterType<Person>(); //------------------------------------------------- var person = container.Resolve<Person>(); person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", 18)) as Person; personA.Self();
這種方式, 就是通過傳參來控制調用哪一個構造函數, 其內部是通過反射的方式去實現的.
如果使用UsingConstructor指定了要使用的構造函數, 就不能使用上面的無參方式去實現了, 會報錯的.
builder.RegisterType<Person>().UsingConstructor(typeof(string), typeof(int)); //------------------------------------------------- //var person = container.Resolve<Person>(); 這種方式就會報錯 //person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", 18)) as Person; personA.Self();
有圖有真相哦.
二、額外的構造函數參數
添加構造函數, 有兩個地方可以添加, 一個是在注冊的時候添加, 另一個是Resolve的時候添加, 就如同上面這個例子中的personA一樣的.
那下面就來說一說注冊的時候添加吧.
builder.RegisterType<Person>().WithParameters(new NamedParameter[] { new NamedParameter("name", "sniper"), new NamedParameter("age", 20) }); //------------------------------------------------- var person = container.Resolve<Person>(); person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", 18)) as Person; personA.Self();
這個時候, 我發現, 無參的寫法和有參的寫法, 都不會報錯, 而且, 在創建實例的時候, 都是調用的兩個參數的構造函數
如果這個時候, 我使用一個參數的方式去寫
var personB = container.Resolve(typeof(Person), new NamedParameter("MyPerson", new Dog() { Name = "小花" })) as Person; personB.Self();
這個時候, 會發現, autofac完全沒有理我, 還是用的之前約定的那個構造函數. 真調皮.
這種在注冊時約定參數的方式, 感覺跟注冊實例的方式很像, 為了解答我的疑惑, 不得不親自試驗一遍.
builder.RegisterInstance<Person>(new Person("liang", 22)); //------------------------------------------------- var person = container.Resolve<Person>(); person.Self(); person.Age += 10; var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", 18)) as Person; personA.Self(); person.Age += 10; var personB = container.Resolve(typeof(Person), new NamedParameter("MyPerson", new Dog() { Name = "小花" })) as Person; personB.Self();
從這里看到, 雖然都是在注冊時, 給了構造函數的約定, 但是還是有天差地別的. 注冊實例的方式有點類似于單例.
三、自動裝配
通過程序集掃描的方式, 可以自動裝配, 省去許多配置的工作和重復的工作
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()); builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces(); //------------------------------------------------- var person = container.Resolve<IPerson>(); person.Self(); var personA = container.Resolve<Person>(); personA.Self(); var animal = container.Resolve<IAnimal>(); animal.Say();
這里為什么會調用一個參數的構造函數呢, 為此我修改了Cat類, 加入了兩個構造函數, 一個無參, 一個string name參數, 發現調用的時候, Cat這里還是無參的構造函數.
然后我又修改了Person的一個參數的構造函數, 將參數改為string name, 運行之后發現調用的就是無參的構造函數了, 從這些現象來看, 影響到autofac選擇構造函數的, 應該就是 IAnimal 這個了. 然后我又加了一個三參構造函數, Person(IAnimal myPerson, string name, int age), 發現還是調用的無參構造函數.
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()); builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces(); //------------------------------------------------- var person = container.Resolve<IPerson>(); person.Self();
我大致看了一下源碼
這個方法中, 程序會根據參數去查找是否有容器中的參數, 如果有的話, 會選擇使用匹配上的構造函數, 這里有一個原則, 就是使用匹配個數最多的那個構造函數, 但是這個構造函數又要做到參數盡可能的少. 是不是有點暈, 給個例子就清晰了
public Person(string name) { Console.WriteLine("一個參數name構造函數"); this.Name = name; } public Person(IAnimal MyPerson) { Console.WriteLine("兩個參數IAnimal, IGo構造函數"); adopt = MyPerson; } public Person(IAnimal MyPerson, IGo go) { Console.WriteLine("兩個參數IAnimal, IGo構造函數"); adopt = MyPerson; this.go = go; } public Person(IAnimal myPerson, string name, int age) { Console.WriteLine("三個參數構造函數"); this.Name = name; this.Age = age; adopt = myPerson; } public Person(IAnimal myPerson, IGo go, string name, int age) { Console.WriteLine("四個參數構造函數"); this.Name = name; this.Age = age; adopt = myPerson; this.go = go; }
ok, 自動匹配規則已經浮出水面了
文章列表