四、面向雲的.net core開發框架基礎設施層-應用程式集和類的查找

来源:http://www.cnblogs.com/BenDan2002/archive/2016/10/26/5996724.html
-Advertisement-
Play Games

在編寫開發框架的時候,經常會遇到要找出應用所用到的所有程式集和類,然後進行下一步的處理。 例如,我們有一個通用控制項類BaseControl,各種富文本編輯器控制項、表格控制項、分頁控制項等都繼承於通用控制項類BaseControl。甚至CMS這個項目的評論等控制項也會繼承該通用控制項類BaseControl。我 ...


在編寫開發框架的時候,經常會遇到要找出應用所用到的所有程式集和類,然後進行下一步的處理。

例如,我們有一個通用控制項類BaseControl,各種富文本編輯器控制項、表格控制項、分頁控制項等都繼承於通用控制項類BaseControl。甚至CMS這個項目的評論等控制項也會繼承該通用控制項類BaseControl。我們有一個需求,就是要做一個下拉列表,列出所有的控制項。因為控制項會分散在不同的程式集中,這樣我們必然會搜索當前應用中的所有程式集,從中找出所有繼承於BaseControl的控制項子類。這就是控制項的列表。(如果我懶病不發作,能夠寫的夠久的話,自定義表單、自定義查詢等技術點可以看到這個需求。)

下麵的方法是找到所有的應用程式集:

 1         private static IEnumerable<Assembly> GetAssemblies()
 2         {
 3             List<Assembly> assemblies = new List<Assembly>();
 4 
 5             //以下2行,總是認為所有的個人程式集都依賴於core
 6             Type type = typeof(ReflectionHelper);
 7 
 8             var libs = DependencyContext.Default.CompileLibraries;
 9             foreach (CompilationLibrary lib in libs)
10             {
11                 //if (lib.Name.StartsWith("Microsoft") || lib.Name.StartsWith("System") || lib.Name.Contains(".System.") || lib.Name.StartsWith("NuGet") || lib.Name.StartsWith("AutoMapper")) continue;
12                 if (lib.Serviceable) continue;
13                 if (lib.Type == "package") continue;
14 
15                 var assembly = Assembly.Load(new AssemblyName(lib.Name));
16                 assemblies.Add(assembly);
17 
18                 //以下,總是認為所有的個人程式集都依賴於core
19 
20                 ////過濾掉“動態生成的”
21                 //if (assembly.IsDynamic) continue;
22 
23                 //if (assembly.FullName == type.AssemblyQualifiedName.Replace(type.FullName + ", ", ""))
24                 //{
25                 //    assemblies.Add(assembly);
26                 //    continue;
27                 //}
28 
29                 //if (assembly.GetReferencedAssemblies().Any(ass => ass.FullName == type.AssemblyQualifiedName.Replace(type.FullName + ", ", "")))
30                 //{
31                 //    assemblies.Add(assembly);
32                 //}
33             }
34 
35             return assemblies;
36         }

此處有個假設,第6行Type type = typeof(ReflectionHelper)。其中ReflectionHelper是核心應用程式集中的一個靜態類,而核心應用程式集假設會被所有的應用程式集所引用。如果該假設不成立,需要將19-22行的註釋去掉,針對每個找到的程式集獲取所有引用的程式集。

if (lib.Serviceable) continue;和if (lib.Type == "package") continue; 這兩行的意思是排除所有的系統程式集、Nuget下載包,減少搜索範圍,提高效率。(這2行暫未最終確認。)

找到所有應用程式集後,下一步該獲取所有繼承於BaseControl的控制項子類。因為控制項子類繼承於BaseControl,因此子類所在的應用程式集必然引用BaseControl的應用程式集。通用寫法如下:

 1         #region 類型搜索
 2         /// <summary>
 3         /// 獲取子類型
 4         /// </summary>
 5         /// <param name="type">父類型</param>
 6         /// <returns></returns>
 7         public static IEnumerable<Type> GetSubTypes(Type type)
 8         {
 9             var assemblies = _Assemblies.Where(a =>
10             {
11                 Assembly assembly = type.GetTypeInfo().Assembly;
12                 //基類所在程式集或依賴於基類的其他程式集
13                 return a.FullName == assembly.FullName || a.GetReferencedAssemblies().Any(ra => ra.FullName == assembly.FullName);
14             });
15 
16             TypeInfo typeInfo = type.GetTypeInfo();
17 
18             return assemblies.SelectMany(a =>
19             {
20                 return a.GetTypes().Where(t =>
21                 {
22                     if (type == t)
23                     {
24                         return false;
25                     }
26 
27                     TypeInfo tInfo = t.GetTypeInfo();
28 
29                     if (tInfo.IsAbstract || !tInfo.IsClass || !tInfo.IsPublic)
30                     {
31                         return false;
32                     }
33 
34                     if (typeInfo.IsGenericTypeDefinition)
35                     {
36                         return type.IsAssignableFromGenericType(t);
37                     }
38 
39                     return type.IsAssignableFrom(t);
40                 });
41             });
42         }
43 
44         /// <summary>
45         /// 獲取子類型
46         /// </summary>
47         /// <typeparam name="T">父類型</typeparam>
48         /// <returns></returns>
49         public static IEnumerable<Type> GetSubTypes<T>()
50         {
51             return GetSubTypes(typeof(T));
52         }
53         #endregion

其中_Assemblies是從GetAssemblies()方法返回的結果。

這樣就能夠獲取當前的子類列表IEnumerable<Type>,可是如果用下拉列表展示,總不能顯示類似namespace.classname, assemblyname的樣子吧,這樣會被客戶罵的。應該下拉出來的是中文名,例如富文本編輯器、文件上傳、分頁、自動完成等。

如果我們在BaseControl中增加一個抽象的Name屬性,各個子類實現時override這個屬性,標識該控制項的中文名,倒是可以實現,不過在獲取Name屬性時,必須要實例化各個子類,天知道子類的構造函數有哪些參數。因此我們應該採取其他方式。建一個TypeNameAttribute。具體實現如下:

  1     /// <summary>
  2     /// 子類中,甚至TypeName,包括中英文及屬性,以便反射使用
  3     /// </summary>
  4     [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
  5     public class TypeNameAttribute : Attribute
  6     {
  7         private string _Code, _Name, _Description;
  8         /// <summary>
  9         /// 英文
 10         /// </summary>
 11         public string Code
 12         {
 13             get
 14             {
 15                 return _Code;
 16             }
 17             set
 18             {
 19                 _Code = value;
 20             }
 21         }
 22         /// <summary>
 23         /// 中文
 24         /// </summary>
 25         public string Name
 26         {
 27             get
 28             {
 29                 return _Name;
 30             }
 31             set
 32             {
 33                 _Name = value;
 34             }
 35         }
 36         /// <summary>
 37         /// 描述
 38         /// </summary>
 39         public string Description
 40         {
 41             get
 42             {
 43                 return _Description;
 44             }
 45             set
 46             {
 47                 _Description = value;
 48             }
 49         }
 50         /// <summary>
 51         /// 構造函數
 52         /// </summary>
 53         /// <param name="code">英文</param>
 54         /// <param name="name">中文</param>
 55         /// <param name="description">描述</param>
 56         public TypeNameAttribute(string code, string name, string description)
 57         {
 58             this._Code = code;
 59             this._Name = name;
 60             this._Description = description;
 61         }
 62 
 63         /// <summary>
 64         /// 構造函數
 65         /// </summary>
 66         /// <param name="code">英文</param>
 67         /// <param name="name">中文</param>
 68         public TypeNameAttribute(string code, string name) : this(code, name, string.Empty)
 69         {
 70         }
 71     }
 72 
 73     /// <summary>
 74     /// TypeName的工具類
 75     /// </summary>
 76     public static class TypeNameHelper
 77     {
 78         public static ConcurrentDictionary<Type, List<TypeNameHelperInfo>> list = new ConcurrentDictionary<Type, List<TypeNameHelperInfo>>();
 79 
 80         public static TypeNameHelperInfo GetTypeNameHelperInfo<T>(string code)
 81         {
 82             List<TypeNameHelperInfo> list = GetTypeNameHelperList<T>();
 83 
 84             return list.SingleOrDefault(info => info.Code == code);
 85         }
 86 
 87         /// <summary>
 88         /// 根據基類,獲取所有子類的TypeName
 89         /// </summary>
 90         /// <typeparam name="T">基類型</typeparam>
 91         /// <returns>子類的TypeName信息</returns>
 92         public static List<TypeNameHelperInfo> GetTypeNameHelperList<T>()
 93         {
 94             if (list.ContainsKey(typeof(T)))
 95             {
 96                 return list[typeof(T)];
 97             }
 98 
 99             List<TypeNameHelperInfo> result = new List<TypeNameHelperInfo>();
100 
101             IEnumerable<Type> typeList = ReflectionHelper.GetSubTypes<T>();
102 
103             foreach (Type type in typeList)
104             {
105                 try
106                 {
107                     TypeNameAttribute attribute = ReflectionHelper.GetCustomAttribute<TypeNameAttribute>(type);
108                     result.Add(new TypeNameHelperInfo()
109                     {
110                         Code = attribute.Code,
111                         Name = attribute.Name,
112                         Description = attribute.Description,
113                         Type = type
114                     });
115                 }
116                 catch
117                 {
118                 }
119             }
120 
121             list[typeof(T)] = result;
122 
123             return result;
124         }
125     }
126 
127     /// <summary>
128     /// TypeName的信息類
129     /// </summary>
130     public class TypeNameHelperInfo
131     {
132         /// <summary>
133         /// 英文
134         /// </summary>
135         public string Code { get; set; }
136         /// <summary>
137         /// 中文
138         /// </summary>
139         public string Name { get; set; }
140         /// <summary>
141         /// 描述
142         /// </summary>
143         public string Description { get; set; }
144         /// <summary>
145         /// 類型
146         /// </summary>
147         public Type Type { get; set; }
148     }

最終就可以通過TypeNameHelper.GetTypeNameHelperList<BaseControl>()就可以獲取所有的控制項子類,子類列表存放在List<TypeNameHelperInfo>


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

-Advertisement-
Play Games
更多相關文章
  • 通常在 Shell 中執行命令的時候,我們會在輸入命令的下方看到執行結果,操作系統預設將命令的執行結果輸出到顯示器上。當然,我們也可以手動的指定輸出路徑,或者輸入路徑,這就是 I/O 重定向。 1.標準輸出重定向 使用 cat 命令,命令的執行結果將會列印在屏幕中。 我們使用 > 來進行輸出重定向, ...
  • 1.值類型: 1 static void Main(string[] args) 2 { 3 int a = 5; 4 int b = 3; 5 NumVal(a, b); 6 Console.WriteLine("a={0},b={1}", a, b); //輸出結果為:a=5,b=3 7 8 C ...
  • 由於項目需要在首頁搞一個訂單數量的走勢圖,經過多方查找,體驗,感覺ECharts不錯,封裝的很細,我們只需要看自己需要那種類型的圖表,搞定好自己的json數據就OK。至於說如何體現出來,官網的教程很詳細。大家可以去看下。大概瞭解下用法就OK。 百度ECharts 3:http://echarts.b ...
  • 第一篇 C#中的委托和事件 第二篇 C#中的委托和事件(續) 首先,張子陽先生的這是兩篇關於委托和事件間關係的文章,是目前為止我讀過的介紹委托和事件以及非同步調用最簡明清晰文章,作者通過非常有節奏的“標題”->“問題”->“思路”->“實現”->“講解”的結構,分步驟一步一步地將委托和事件的實現、應用 ...
  • 上一章中筆者講到關於Linq和EF的用法。並以hibernate來進行講解。那麼本章筆者來講一下C#的Asp.Net。即是在B/S模式下開發。現在企業大部分的業務都是面向B/S模式的。所以對於Asp.Net的瞭解變得必不可少的知識點。筆者在從事JAVA開發的時候,很少看到有關於Awt和Swing開發 ...
  • 目錄索引 【無私分享:ASP.NET CORE 項目實戰】目錄索引 簡介 很長時間沒有來更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其實已經完成了一個框架了,並且正在準備在生產環境中試用,但是很多東西也是出於自己理解的膚淺和技術的不斷更新,經常變動,所以,如果自己還沒有完全搞好,就 ...
  • 不要急,源代碼分享在最底部,先問大家一個問題,你在寫開放的API介面時是如何保證數據的安全性的?先來看看有哪些安全性問題在開放的api介面中,我們通過http Post或者Get方式請求伺服器的時候,會面臨著許多的安全性問題,例如: 1. 請求來源(身份)是否合法? 2. 請求參數被篡改? 3. 請... ...
  • 一、概念 Moq是利用諸如Linq表達式樹和Lambda表達式等·NET 3.5的特性,為·NET設計和開發的Mocking庫。Mock字面意思即模擬,模擬對象的行為已達到欺騙目標(待測試對象)的效果. Moq模擬類類型時,不可模擬密封類,不可模擬靜態方法(適配器可解決),被模擬的方法及屬性必須被v ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...