ASP.NET MVC實(shí)現(xiàn)依賴注入的完整過(guò)程
前言
在java的spring中有自動(dòng)注入功能,使得代碼變得更加簡(jiǎn)潔靈活,所以想把這個(gè)功能移植到c#中,接下來(lái)逐步分析實(shí)現(xiàn)過(guò)程
1.使用自動(dòng)注入場(chǎng)景分析
在asp.net mvc中,無(wú)論是什么代碼邏輯分層,最終的表現(xiàn)層為Controller層,所以我們注入點(diǎn)就是在Controller中,這里我們需要替換默認(rèn)的ControllerFactory,掃描代碼中標(biāo)記需要注入的對(duì)象,進(jìn)行實(shí)例化注入
public class FastControllerFactory : DefaultControllerFactory { public override IController CreateController(RequestContext requestContext, string controllerName) { Type type = this.GetControllerType(requestContext, controllerName); Object obj = GetControllerInstance(requestContext, type); //Controller中標(biāo)記AutoWired屬性的自動(dòng)注入 List<FieldInfo> AutoWiredFieldList = type.GetRuntimeFields().Where(f => f.GetCustomAttribute(typeof(AutoWired)) != null).ToList(); foreach (FieldInfo field in AutoWiredFieldList) { field.SetValue(obj, InjectUtil.Container.Resolve(field.FieldType)); } return obj as IController; } }
FastControllerFactory就是我們自定義的一個(gè)Controller工廠,重寫CreateController方法,對(duì)標(biāo)記了AutoWired這個(gè)自定義注解的變量,從Bean容器中取出實(shí)例進(jìn)行賦值,同時(shí)我們還需要在Global文件中的Start方法中,進(jìn)行默認(rèn)工廠進(jìn)行替換
ControllerBuilder.Current.SetControllerFactory(new FastControllerFactory());
2.IOC容器的實(shí)現(xiàn)
c#中的自定義容器有很多開源成熟的框架,例如AutoFac等,這里我們是自己實(shí)現(xiàn)一個(gè)輕量級(jí)的版本
源碼地址:https://gitee.com/grassprogramming/FastIOC
這里就重點(diǎn)說(shuō)一下如何在asp.net mvc中的使用,首先我們需要對(duì)需要注入的Bean對(duì)象進(jìn)行標(biāo)記,這個(gè)標(biāo)記就叫做Component,
在asp.net mvc Global文件中的Start方法中,我們需要將整個(gè)項(xiàng)目中需要自動(dòng)注入的Bean加入到容器中
public class InjectUtil { public static ContainerBuilder Container; public static void Init() { Container = new ContainerBuilder(); //獲取所有程序集 var assemblies = System.Web.Compilation.BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray(); //注入所有Component組件 Container.RegisterAssemblyTypes(assemblies, typeof(Component),true); Container.Build(); } }
到這里Controller層面的事項(xiàng)就已經(jīng)完成了,接下來(lái)就需要在IOC容器中初始化Bean實(shí)例方法中進(jìn)一步處理
private Object GetInstance(RegisterEntity Entity) { Object obj = null; if (Entity.IsEnableIntercept) { bool IsExtend = Entity.RealType == Entity.RegistType; obj = DynamictProxy.CreateProxyObject(Entity.RealType, Entity.RegistType, Entity.InterceptType, IsExtend, Entity.IsInterceptAllMethod); } else { var constructors = Entity.RegistType.GetConstructors(); obj = constructors[0].Invoke(new Object[] { }); } //這里使用單例模式將實(shí)例化Instance存儲(chǔ),提前暴露未進(jìn)行后續(xù)設(shè)置的對(duì)象實(shí)例 if (!SingleInstanceDic.ContainsKey(Entity.RealType)) { SingleInstanceDic.Add(Entity.RealType, obj); } //如果這個(gè)class標(biāo)記了Component,且有標(biāo)記了AutoWired的Field,進(jìn)行自動(dòng)注入 if (Entity.RealType.GetCustomAttribute(typeof(Component), true) != null) { //這里要使用GetRuntimeFields,此方法返回在指定類型上定義的所有字段,包括繼承,非公共,實(shí)例和靜態(tài)字段。 foreach (FieldInfo Field in Entity.RealType.GetRuntimeFields()) { if (Field.GetCustomAttribute(typeof(AutoWired), true) != null) { Type FieldType = Field.FieldType; if (Contains(FieldType)) { //判斷單例存儲(chǔ)中是否包含,如果有,取出賦值,這里可以防止循環(huán)依賴導(dǎo)致的死循環(huán) if (SingleInstanceDic.ContainsKey(FieldType)) { Field.SetValue(obj, SingleInstanceDic[FieldType]); } else { Field.SetValue(obj, Resolve(FieldType)); } } } } } return obj; }
GetInstance方法就是實(shí)例化Bean對(duì)象的核心方法,其實(shí)很簡(jiǎn)單,就是通過(guò)反射創(chuàng)建對(duì)象,其中需要注意的有兩點(diǎn)
1)對(duì)于一個(gè)Bean初始化時(shí)需要掃描Bean中的所有變量,如果內(nèi)部還有依賴注入的嵌套對(duì)象,需要使用遞歸,直到?jīng)]有需要注入的Field
2)我這里使用的是單例模式,因?yàn)樵跍y(cè)試過(guò)程中可能存在在A類中對(duì)B進(jìn)行依賴注入,在B類中對(duì)A進(jìn)行依賴注入,常規(guī)創(chuàng)建過(guò)程,如果使用遞歸進(jìn)行掃描,就會(huì)進(jìn)入死循環(huán),內(nèi)存溢出,所以使用對(duì)象的單例,一旦創(chuàng)建就放入字典中,如果再次掃描到該對(duì)象需要注入,則直接取出使用,就避免了循環(huán)引用
3.其他
對(duì)其他不在Controller中使用的類需要依賴注入,則需要直接從IOC的Bean容器取出使用
private AuthUtil @AuthUtil = InjectUtil.Container.Resolve<AuthUtil>();
功能到這里就全部分析完畢了,最后打個(gè)廣告,自己寫的ASP.NET MVC快速開發(fā)框架,希望支持一波
地址:https://gitee.com/grassprogramming/FastExecutor
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)我們的支持。
上一篇:ASP.NET Core中如何利用Csp標(biāo)頭對(duì)抗Xss攻擊
欄 目:ASP.NET
下一篇:為HttpClient添加默認(rèn)請(qǐng)求報(bào)頭的四種解決方案
本文標(biāo)題:ASP.NET MVC實(shí)現(xiàn)依賴注入的完整過(guò)程
本文地址:http://mengdiqiu.com.cn/a1/ASP_NET/10878.html
您可能感興趣的文章
- 01-11如何給asp.net core寫個(gè)簡(jiǎn)單的健康檢查
- 01-11docker部署Asp.net core應(yīng)用的完整步驟
- 01-11ASP.NET Core靜態(tài)文件的使用方法
- 01-11asp.net Core3.0區(qū)域與路由配置的方法
- 01-11ASP.Net Core中使用枚舉類而不是枚舉的方法
- 01-11.NET Core 3.0 可回收程序集加載上下文的實(shí)現(xiàn)
- 01-11Asp.net core利用MediatR進(jìn)程內(nèi)發(fā)布/訂閱詳解
- 01-11ASP.NET Core中間件計(jì)算Http請(qǐng)求時(shí)間示例詳解
- 01-11asp.net core集成JWT的步驟記錄
- 01-11ASP.NET Core MVC學(xué)習(xí)教程之路由(Routing)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-11vscode extension插件開發(fā)詳解
- 01-11VsCode插件開發(fā)之插件初步通信的方法
- 01-11如何給asp.net core寫個(gè)簡(jiǎn)單的健康檢查
- 01-11.net core高吞吐遠(yuǎn)程方法如何調(diào)用組件
- 01-11淺析.Net Core中Json配置的自動(dòng)更新
- 01-11.NET開發(fā)人員關(guān)于ML.NET的入門學(xué)習(xí)
- 01-11.NET Core 遷移躺坑記續(xù)集之Win下莫名其
- 01-11.net core webapi jwt 更為清爽的認(rèn)證詳解
- 01-11docker部署Asp.net core應(yīng)用的完整步驟
- 01-11ASP.NET Core靜態(tài)文件的使用方法
隨機(jī)閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子