ASP.NET MVC實現依賴註入

来源:https://www.cnblogs.com/yanpeng19940119/archive/2019/09/10/11502385.html
-Advertisement-
Play Games

在java的spring中有自動註入功能,使得代碼變得更加簡潔靈活,所以想把這個功能移植到c#中,接下來逐步分析實現過程 1.使用自動註入場景分析 在asp.net mvc中,無論是什麼代碼邏輯分層,最終的表現層為Controller層,所以我們註入點就是在Controller中,這裡我們需要替換默 ...


在java的spring中有自動註入功能,使得代碼變得更加簡潔靈活,所以想把這個功能移植到c#中,接下來逐步分析實現過程

1.使用自動註入場景分析

在asp.net mvc中,無論是什麼代碼邏輯分層,最終的表現層為Controller層,所以我們註入點就是在Controller中,這裡我們需要替換預設的ControllerFactory,掃描代碼中標記需要註入的對象,進行實例化註入

 public class FastControllerFactory : DefaultControllerFactory
    {
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            Type type = this.GetControllerType(requestContext, controllerName);
            Object obj = GetControllerInstance(requestContext, type);

            //Controller中標記AutoWired屬性的自動註入
            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就是我們自定義的一個Controller工廠,重寫CreateController方法,對標記了AutoWired這個自定義註解的變數,從Bean容器中取出實例進行賦值,同時我們還需要在Global文件中的Start方法中,進行預設工廠進行替換

ControllerBuilder.Current.SetControllerFactory(new FastControllerFactory());

2.IOC容器的實現

c#中的自定義容器有很多開源成熟的框架,例如AutoFac等,這裡我們是自己實現一個輕量級的版本

源碼地址:https://gitee.com/grassprogramming/FastIOC

這裡就重點說一下如何在asp.net mvc中的使用,首先我們需要對需要註入的Bean對象進行標記,這個標記就叫做Component,

在asp.net mvc Global文件中的Start方法中,我們需要將整個項目中需要自動註入的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層面的事項就已經完成了,接下來就需要在IOC容器中初始化Bean實例方法中進一步處理

       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[] { });
            }
            //這裡使用單例模式將實例化Instance存儲,提前暴露未進行後續設置的對象實例
            if (!SingleInstanceDic.ContainsKey(Entity.RealType))
            {
                SingleInstanceDic.Add(Entity.RealType, obj);
            }
        
            //如果這個class標記了Component,且有標記了AutoWired的Field,進行自動註入
            if (Entity.RealType.GetCustomAttribute(typeof(Component), true) != null)
            {
                //這裡要使用GetRuntimeFields,此方法返回在指定類型上定義的所有欄位,包括繼承,非公共,實例和靜態欄位。
                foreach (FieldInfo Field in Entity.RealType.GetRuntimeFields())
                {
                    if (Field.GetCustomAttribute(typeof(AutoWired), true) != null)
                    {
                        Type FieldType = Field.FieldType;
                        if (Contains(FieldType))
                        {
                            //判斷單例存儲中是否包含,如果有,取出賦值,這裡可以防止迴圈依賴導致的死迴圈
                            if (SingleInstanceDic.ContainsKey(FieldType))
                            {
                                Field.SetValue(obj, SingleInstanceDic[FieldType]);
                            }
                            else
                            {
                                Field.SetValue(obj, Resolve(FieldType));
                            }
                           
                        }
                    }
                }
            }
            return obj;

        }

 

GetInstance方法就是實例化Bean對象的核心方法,其實很簡單,就是通過反射創建對象,其中需要註意的有兩點

1)對於一個Bean初始化時需要掃描Bean中的所有變數,如果內部還有依賴註入的嵌套對象,需要使用遞歸,直到沒有需要註入的Field

2)我這裡使用的是單例模式,因為在測試過程中可能存在在A類中對B進行依賴註入,在B類中對A進行依賴註入,常規創建過程,如果使用遞歸進行掃描,就會進入死迴圈,記憶體溢出,所以使用對象的單例,一旦創建就放入字典中,如果再次掃描到該對象需要註入,則直接取出使用,就避免了迴圈引用

3.其他

對其他不在Controller中使用的類需要依賴註入,則需要直接從IOC的Bean容器取出使用

 private AuthUtil @AuthUtil = InjectUtil.Container.Resolve<AuthUtil>();

功能到這裡就全部分析完畢了,最後打個廣告,自己寫的ASP.NET MVC快速開發框架,希望支持一波

地址:https://gitee.com/grassprogramming/FastExecutor


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Netty簡介 Netty是一個高性能,高可擴展性的非同步事件驅動的網路應用程式框架,它極大的簡化了TCP和UDP客戶端和伺服器端網路開發。它是一個NIO框架,對Java NIO進行了良好的封裝。作為一個非同步NIO框架,Netty的所有IO操作都是非同步非阻塞的,通過Future-Listener機制, ...
  • 本人免費整理了Java高級資料,一共30G,需要自己領取;傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 運行時數據區域 JVM載執行Java程式的過程中會把它所管理的記憶體劃分為若幹個不同的數據區域。這些區域都有各自的用途,以及創建和銷毀的 ...
  • 在 python 中,數字類型主要包括整數、浮點數和複數。 1.整數 整數用來表示整數數值,即沒有小數部分的數值。在 python 中,整數包括正整數、負整數和0,並且他的位數是任意的 整數類型包括十進位整數、八進位整數、十六進位整數和二進位整數 註意 不能以0作為十進位數的開頭(0除外)。 在 p ...
  • 某位 A 同學發了我一張截圖,問為何結果中出現了負數? 看了圖,我第一感覺就是數據溢出了。數據超出能表示的最大值,就會出現奇奇怪怪的結果。 然後,他繼續發了張圖,內容是 print(100000\ 208378),就是直接列印上圖的 E[0]\ G[0],結果是 20837800000,這是個正確的 ...
  • 因為重裝了系統,重新配置JDK環境變數,過程中遇到一些問題,分享一下。 本文圖片較多,適合新手 -- ( : 工具: Window 10 JDK1.8,官網或百度雲很好找 JDK1.8,官網或百度雲很好找 步驟: 一、安裝 單擊安裝包,進入以下界面: 直接點擊下一步。 直接點擊下一步。 安裝路徑建議 ...
  • 我不打算解釋什麼是 ,也不解釋為什麼要使用它。我希望你已經在其他地方瞭解過,如果沒有,你可以使用 去搜索它。在本文中,我將告訴您如何使用專門針對 和`RxJava`的響應式編程。讓我們開始吧。 1.預備知識 在你繼續閱讀之前,我希望你能理解如何使用 和`RxJava REST API`。 如果不能, ...
  • 上次在 asp.net core 從單機到集群 一文中提到存儲還不支持分散式,並立了一個 flag > 基於 github 或者 開源中國的碼雲實現一個 storage 於是這兩天就來填坑了。。 ...
  • 一、static關鍵字 下麵我設計了一個房貸利率上浮類(用來計算房貸利率上浮多少): 上面例子的問題在於基準利率這個屬性是所有房貸利率上浮對象共用的屬性,而不是每個房貸利率上浮對象都擁有一個基準利率。所以要把基準利率這個屬性設置成共用的需要使用static關鍵字,第二版房貸利率上浮類: 靜態自動屬性 ...
一周排行
    -Advertisement-
    Play Games
  • JWT(JSON Web Token)是一種用於在網路應用之間傳遞信息的開放標準(RFC 7519)。它使用 JSON 對象在安全可靠的方式下傳遞信息,通常用於身份驗證和信息交換。 在Web API中,JWT通常用於對用戶進行身份驗證和授權。當用戶登錄成功後,伺服器會生成一個Token並返回給客戶端 ...
  • 老周在幾個世紀前曾寫過樹莓派相關的 iOT 水文,之所以沒寫 Nano Framework 相關的內容,是因為那時候這貨還不成熟,可玩性不高。不過,這貨現在已經相對完善,老周都把它用在項目上了——第一個是自製的智能插座,這個某寶上50多塊可以買到,搜“esp32 插座”就能找到。一種是 86 型盒子 ...
  • 引言 上一篇我們創建了一個Sample.Api項目和Sample.Repository,並且帶大家熟悉了一下Moq的概念,這一章我們來實戰一下在xUnit項目使用依賴註入。 Xunit.DependencyInjection Xunit.DependencyInjection 是一個用於 xUnit ...
  • 在 Avalonia 中,樣式是定義控制項外觀的一種方式,而控制項主題則是一組樣式和資源,用於定義應用程式的整體外觀和感覺。本文將深入探討這些概念,並提供示例代碼以幫助您更好地理解它們。 樣式是什麼? 樣式是一組屬性,用於定義控制項的外觀。它們可以包括背景色、邊框、字體樣式等。在 Avalonia 中,樣 ...
  • 在處理大型Excel工作簿時,有時候我們需要在工作表中凍結窗格,這樣可以在滾動查看數據的同時保持某些行或列固定不動。凍結窗格可以幫助我們更容易地導航和理解複雜的數據集。相反,當你不需要凍結窗格時,你可能需要解凍它們以獲得完整的視野。 下麵將介紹如何使用免費.NET庫通過C#實現凍結Excel視窗以鎖 ...
  • .NET 部署 IIS 的簡單步驟一: 下載 dotnet-hosting-x.y.z-win.exe ,下載地址:.NET Downloads (Linux, macOS, and Windows) (microsoft.com) .NET 部署 IIS 的簡單步驟二: 選擇對應的版本,點擊進入詳 ...
  • 拓展閱讀 資料庫設計工具-08-概覽 資料庫設計工具-08-powerdesigner 資料庫設計工具-09-mysql workbench 資料庫設計工具-10-dbdesign 資料庫設計工具-11-dbeaver 資料庫設計工具-12-pgmodeler 資料庫設計工具-13-erdplus ...
  • 初識STL STL,(Standard Template Library),即"標準模板庫",由惠普實驗室開發,STL中提供了非常多對信息學奧賽很有用的東西。 vector vetor是STL中的一個容器,可以看作一個不定長的數組,其基本形式為: vector<數據類型> 名字; 如: vector ...
  • 前言 最近自己做了個 Falsk 小項目,在部署上伺服器的時候,發現雖然不乏相關教程,但大多都是將自己項目代碼複製出來,不講核心邏輯,不太簡潔,於是將自己部署的經驗寫成內容分享出來。 uWSGI 簡介 uWSGI: 一種實現了多種協議(包括 uwsgi、http)並能提供伺服器搭建功能的 Pytho ...
  • 1 文本Embedding 將整個文本轉化為實數向量的技術。 Embedding優點是可將離散的詞語或句子轉化為連續的向量,就可用數學方法來處理詞語或句子,捕捉到文本的語義信息,文本和文本的關係信息。 ◉ 優質的Embedding通常會讓語義相似的文本在空間中彼此接近 ◉ 優質的Embedding相 ...