Autofac之自動裝配

從容器中的可用服務中選擇一個構造函數來創造對象,這個過程叫做自動裝配。這個過程是通過反射實現的

默認

思考這么一個問題,如果注冊類型中存在多個構造函數,那么Autofac會選擇哪一個來創建類型的實例

答案是"盡可能最多參數"

class ConstructorClass
{private Class1 _clas1;private Class2 _clas2;private Class3 _clas3 = null;public ConstructorClass(){_clas1 = null; _clas2 = new Class2 { Id = -1 };}public ConstructorClass(Class1 clas1, Class2 clas2){_clas1 = clas1; _clas2 = clas2;}public ConstructorClass(Class2 clas2, Class3 clas3){_clas2 = clas2; _clas3 = clas3;}public ConstructorClass(Class2 clas2, Class3 clas3, Guid guid){_clas1 = new Class1 { Id = guid }; _clas2 = clas2; _clas3 = clas3;}public ConstructorClass(Class1 clas1, Class2 clas2, Class3 clas3){_clas1 = clas1; _clas2 = clas2; _clas3 = clas3;}public override string ToString(){return string.Format("{{Class1.Id: {0}, Class2.Id: {1}, Class3: {2}}}",_clas1 == null ? "null" : _clas1.Id.ToString(),_clas2 == null ? "null" : _clas2.Id.ToString(),_clas3 == null ? "null" : "not null");}
}class Class1
{public Guid Id { get; set; }
}class Class2
{public int Id { get; set; }
}class Class3
{}static void Main(string[] args)
static void Main(string[] args)
{//注冊容器var builder = new ContainerBuilder();//向容器中注冊類型builder.RegisterType<ConstructorClass>();builder.RegisterType<Class2>();builder.RegisterType<Class3>();using (var container = builder.Build()){#region Resolve對象構造方法選擇原則(當我們注冊的類型擁有多個構造方法,那么在Resolve時,將會以盡可能最多參數構造方法為準)var obj = container.Resolve<ConstructorClass>();Console.WriteLine(obj);#endregion
    }Console.ReadKey();
}

該實例顯示,選擇的是第三個構造函數,參數為(Class2 clas2, Class3 clas3),

按照字面上里說明”最多參數“,那么理應執行的是最后一個構造方法或倒數第二個構造方法,但是為什么卻是第三個,這也就是為什么我要加“盡可能”三字了。

先拋開為什么執行的第三個構造方法,我們還是會有疑問”如果執行的是第三個構造方法,那么Class2和Class3參數分別賦的是什么值?值又是從哪兒來?“,這里就涉及到了后面會講到的構造注入。我們可以看到,在進行類型注冊時,我們是對Class2和Class3進行了注冊的,而ConstructorClass又是通過Autofac進行獲取的,所以Class2和Class3參數的值是由Autofac進行初始化賦值的,Class2和Class3沒有自定義構造方法,所以調用的是默認的空構造方法。

在知道Class2和Class3參數的初始化與賦值緣由后,我們再來看看之前的那個問題,為什么會執行第三個構造方法,其實現在就好明白了,因為最后兩個的構造方法,一個需要額外的Guid類型參數,另一個需要Class1類型參數,而這兩個類型又沒有經過注冊,如果調用這兩個構造方法,那么Auotofac將不知道應該賦何值給這兩個參數,所以Autofac最終選擇了第三個構造方法。

此時我把第三個構造函數注釋掉之后,會調用第一個構造函數,按照"盡可能最多參數"原則,此時不應該調用第二個嗎?答案是,Autofac會在已注冊的類型中尋找,雖然Class2類型被注冊,第二個構造函數Class1類型參數Autofac不知道如何賦值,所以選擇了默認的構造函數,如果在容器中注冊類型Class1取消掉類型Class3的注冊,此時就會調用第二個構造函數.(Autofac尋找構造函數的規則是在已注冊的類型中尋找參數完全匹配的構造函數)

UsingConstructor:指定使用某個構造函數

通過上面的例子我們知道Autofac創建類型實例時會默認從容器中選擇匹配參數最多的構造函數,此時在容器中將Class1、Class2、Class3類型都注冊,此時默認情況會使用最后一個構造函數,如果如果想要選擇一個不同的構造函數,就需要在注冊的時候就指定它,此時指定使用參數為(Class1 clas1, Class2 clas2)的構造函數

builder.RegisterType<Class1>();
builder.RegisterType<Class2>();
builder.RegisterType<Class3>();
builder.RegisterType<ConstructorClass>().UsingConstructor(typeof(Class1), typeof(Class2));

?額外的構造函數參數

有兩種方式可以添加額外的構造函數參數,在注冊的時候和在檢索的時候。在使用自動裝配實例的時候這兩種都會用到。

注冊時添加參數

使用WithParameters()方法在每一次創建對象的時候將組件和參數關聯起來。

builder.RegisterType<ConstructorClass>().WithParameter("guid", Guid.NewGuid());
//builder.RegisterType<Class1>();//將Class1注冊因為在盡可能最多的原則上,出現了兩個最多參數的構造方法,Autofac不知道應該選擇哪個進行執行
builder.RegisterType<Class2>();
builder.RegisterType<Class3>();

在檢索階段添加參數
在Resolve()的時候提供的參數會覆蓋所有名字相同的參數,在注冊階段提供的參數會覆蓋容器中所有可能的服務。

var obj = container.Resolve<ConstructorClass>(new NamedParameter("guid", Guid.NewGuid()));

?自動裝配

在需要的時候,依然可以創建指定的構造函數創建指定的類。

builder.Register(c => new Clas1());

Resolve的方法簽名為:Resolve<T>(this IComponmentContext context, params Parameter[] parameters)

第一個參數也就是我們使用的container,我們主要關注第二個參數——一個可變的Parameter數組,Parameter是一個抽象類,其中NamedParameter為Parameter的一個子類,除了NamedParameter,還有以下幾種子類拱Resolve時使用:

參數類型

參數說明

NamedParameter

根據名稱進行匹配

PositionalParameter

根據索引進行匹配,注意:起始索引為0

TypedParameter

根據類型進行匹配,注意:傳入多個相同類型的TypedParameter,所有該類型的參數都將采用第一個TypedParameter的值

ResolvedParameter

接收兩個Func參數,兩個Func簽名都接收兩個相同的參數ParameterInfo和IComponmentContext,第一個參數為參數的信息(常使用放射的朋友應該熟悉),第二個參數還是當做IContainer使用就好了。第一個Func的返回值為bool,表明當前這個ResolvedParameter是否使用當前匹配到的參數,如果返回true,則會執行第二個Func;第二個Func返回一個object對象,用于填充構造參數值。

?

下面有一個這些Parameter使用的示例供參考:

復制代碼
class Program
{static void Main(string[] args){var builder = new ContainerBuilder();builder.RegisterType<ParameterClass>();var container = builder.Build();container.Resolve<ParameterClass>(new NamedParameter("value", "namedParameter"),      //匹配名字為value的參數new TypedParameter(typeof (int), 1),                //匹配類型為int的參數new PositionalParameter(4, "positionalParameter"),  //匹配第五個參數(注意,索引位置從0開始)new TypedParameter(typeof (int), -1),               //這個將被拋棄,因為前面已經有一個類型為int的TypedParameternew ResolvedParameter(//第一個Func參數用于返回參數是否符合要求,這里要求參數是類,且命名空間不是System開頭,所以第四個參數將會匹配上(pi, cc) => pi.ParameterType.IsClass && !pi.ParameterType.Namespace.StartsWith("System"),//第二個Func參數在第一個Func執行結果為true時執行,用于給參數賦值,也就是第四個參數的值為這個Func的執行結果(pi, cc) => new Temp {Name = "resolveParameter"}));// 最后的輸出結果為: {x:1, y:1, value:'namedParameter', temp.Name:'resolveParameter', obj:'positionalParameter'}Console.Write("Press any key to continue...");Console.ReadKey();}
}class ParameterClass
{public ParameterClass(int x, int y, string value, Temp temp, object obj){Console.WriteLine("{{x:{0}, y:{1}, value:'{2}', temp.Name:'{3}', obj:'{4}'}}", x, y, value, temp.Name, obj);}
}class Temp
{public string Name { get; set; } 
}
復制代碼

轉載于:https://www.cnblogs.com/GnailGnepGnaw/p/10757340.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279628.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279628.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279628.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

對Emlog 6.0 Beta的完整代碼審計過程

Emlog 6.0 beta版本&#xff0c;這可能是最后一篇關于PHP語言CMS的代碼審計文章&#xff0c;此次將詳細記錄完整的審計過程。 文章基本上完整記錄小東的對此CMS審計過程&#xff0c;或許顯得繁瑣&#xff0c;但代碼審計的過程就是這樣&#xff0c;發現可能項&#xff0c;然后精…

SINOCES 2011

突然發現又好久沒寫過日志了 是在是太懶了… 難得休假去看了眼消費電子 感覺實在是一年不如一年 佳能、索尼不見蹤影&#xff0c;相機滿場沒見一家&#xff08;大牌子是真沒見到&#xff09; 華碩技嘉微星等主板廠商同樣失蹤… PC方面&#xff0c;聯想貌似是來賣電腦包鼠標的&a…

esim卡與ms卡的區別_什么是eSIM,它與SIM卡有何不同?

esim卡與ms卡的區別With the launch of the Apple Watch 3, the term “eSIM” has been thrown around a lot. And now, Google’s Pixel 2 is the first phone to use this new technology, it’s time we take a closer look at what it is, what it does, and what this me…

機器學習實戰之logistic回歸分類

利用logistic回歸進行分類的主要思想&#xff1a;根據現有數據對分類邊界建立回歸公式&#xff0c;并以此進行分類。 logistic優缺點&#xff1a; 優點&#xff1a;計算代價不高&#xff0c;易于理解和實現。缺點&#xff1a;容易欠擬合&#xff0c;分類精度可能不高。 .適用數…

HDU 6343.Problem L. Graph Theory Homework-數學 (2018 Multi-University Training Contest 4 1012)

6343.Problem L. Graph Theory Homework 官方題解: 一篇寫的很好的博客: HDU 6343 - Problem L. Graph Theory Homework - [(偽裝成圖論題的)簡單數學題] 代碼: 1 //1012-6343-數學2 #include<iostream>3 #include<cstdio>4 #include<cstring>5 #include<…

Android GridView LruCache

照片墻這種功能現在應該算是挺常見了&#xff0c;在很多應用中你都可以經常看到照片墻的身影。它的設計思路其實也非常簡單&#xff0c;用一個GridView控件當作“墻”&#xff0c;然后隨著GridView的滾動將一張張照片貼在“墻”上&#xff0c;這些照片可以是手機本地中存儲的&a…

如何在Android TV上自定義推薦行

When you fire up Android TV, the first thing you see is a list of movies and shows the system thinks you’ll like. It’s often full of the latest flicks or hottest news, but sometimes it could just be things relevant to your interests and the apps you have…

遞歸 段錯誤 習題

段錯誤 遞歸里面算階乘 f(10000000)沒有輸出&#xff0c;使用gdb 顯示 SIGSEGV--段錯誤編譯后產生的可執行文件里面保存著什么&#xff1f;UNIX/Linux 用 ELFDOS下用COFFWindows用PE&#xff08;COFF擴充而得&#xff09;段&#xff08;segmentation&#xff09;二進制文件內的…

你知道你常用的dos和linux命令嗎?

功能 Linux MS-DOS 進入到該目錄 cd cd 列舉文件 ls dir 創建目錄 mkdir mkdir 清除屏幕 clear cls 復制文件 cp copy 移動文件 mv move 刪除文件 rm del 查看文件 less more 文件重命名 mv ren 比較文件內容 diff fc 查看當前路徑 pwd chd…

steam串流到手機_如何從手機將Steam游戲下載到PC

steam串流到手機Steam allows you to remotely install games from your smartphone, just like you can with a PlayStation 4 or Xbox One. You can download games to your gaming PC from anywhere, ensuring those big downloads are complete and the game is ready to p…

編寫安裝配置ftp-samba服務腳本

本腳本實例的要求如下&#xff1a; 1、公司有公共共享目錄public,所有員工均可讀寫&#xff0c;但不允許刪除其他員工的文件;不能匿名登錄 2、每部門均有共享目錄&#xff0c;部門經理可讀寫&#xff0c;部門員工可讀&#xff1b; 非本部門員工不能訪問&#xff08;caiwu、rens…

利用java實現excel轉pdf文件

在有些需求當中我們需要抓取字段并且填充到excel表格里面&#xff0c;最后將excel表格轉換成pdf格式進行輸出&#xff0c;我第一次接觸這個需求時&#xff0c;碰到幾個比較棘手的問題&#xff0c;現在一一列出并且提供解決方案。 1&#xff1a;excel轉pdf出現亂碼&#xff1a; …

Jmeter HTTP請求后響應數據顯示亂碼解決方法

Jmeter請求后結果樹里無論是text還是html響應數據顯示亂碼&#xff0c;這是因為jmeter 編碼格式配置文件默認不開啟導致的&#xff0c;解決方法如下&#xff1a; 1&#xff09;進入jmeter-***\bin目錄下&#xff0c;找到jmeter.properties文件&#xff0c;以文本文件形式打開 2…

禁用windows10更新_如何在Windows 10中禁用投影

禁用windows10更新The drop shadows on applications in the Windows 10 preview are really big and suspiciously similar to the ones in OS X, and if they aren’t your speed, you can easily remove them. We actually think they look good, but since somebody out th…

如何訪問 Service?- 每天5分鐘玩轉 Docker 容器技術(99)

前面我們已經學習了如何部署 service&#xff0c;也驗證了 swarm 的 failover 特性。不過截止到現在&#xff0c;有一個重要問題還沒有涉及&#xff1a;如何訪問 service&#xff1f;這就是本節要討論的問題。 為了便于分析&#xff0c;我們重新部署 web_server。 ① docker se…

sqlyog下載

sqlyog下載&#xff08;附注冊碼&#xff09;&#xff1a;http://www.onlinedown.net/soft/24926.htm轉載于:https://www.cnblogs.com/shujuxiong/p/9474496.html

Linux配置手冊(二)配置DHCP服務器

1.檢查是否安裝DHCP服務器軟件 2.掛在RHEL5系統光盤 3.安裝DHCP服務軟件 4.將模板配置文件復制并覆蓋現在的配置文件 5.配置修改dhcpd.conf文件 配置信息 默認租約時間 default-lease-time 最大租約時間 max-lease-time 局域網內所有主機的域名 option domain-name 客戶機所使用…

什么是Google Play保護以及如何確保Android安全?

Android is open, flexible, and all about choice. Unfortunately, that flexibility comes more potential security issues. The good news is that Google has a system in place named Play Protect that helps keep Android secure. Android開放&#xff0c;靈活且具有多…

如何使計算機為您讀取文檔

Since the beginning of the computer age, people have always enjoyed making computers talk to them. These days, that functionality is built right into Windows and you can easily use it to have your PC read documents to you. 自計算機時代開始以來&#xff0c;人…

面試中常問的List去重問題,你都答對了嗎?

2019獨角獸企業重金招聘Python工程師標準>>> 面試中經常被問到的list如何去重&#xff0c;用來考察你對list數據結構&#xff0c;以及相關方法的掌握&#xff0c;體現你的java基礎學的是否牢固。 我們大家都知道&#xff0c;set集合的特點就是沒有重復的元素。如果集…