1. 程式人生 > 其它 >C# 動態獲取程式集資訊

C# 動態獲取程式集資訊

本文通過一個簡單的例項,來講解動態載入Dll需要的知識點。僅供學習分享使用,如有不足之處,還請指正。

在設計模式的策略模式中,需要動態載入程式集資訊。

涉及知識點:

  • AssemblyName類,完整描述程式集的唯一標識, 用來表述一個程式集。
  • Assembly類,在System.Reflection名稱空間下,表示一個程式集,它是一個可重用、無版本衝突並且可自我描述的公共語言執行時應用程式構建基塊。
  • Module類 表述在模組上執行反射,表述一個程式集的模組資訊。
  • Type類,在System名稱空間下,表示型別宣告:類型別、介面型別、陣列型別、值型別、列舉型別、型別引數、泛型型別定義,以及開放或封閉構造的泛型型別。
  • FieldInfo類,發現欄位屬性並提供對欄位元資料的訪問權。
  • MethodInfo類,發現方法的屬性並提供對方法元資料的訪問。
  • EventInfo類,發現事件的屬性並提供對事件元資料的訪問權。
  • ConstructorInfo類,發現類建構函式的屬性並提供對建構函式元資料的訪問權。
  • Activator類,包含特定的方法,用以在本地或從遠端建立物件型別,或獲取對現有遠端物件的引用。此類不能被繼承。
  • BindingFlags類,指定控制繫結和由反射執行的成員和型別搜尋方法的標誌。在獲取方法時,第二個引數會用到

效果圖

如下圖所示:

核心程式碼

具體程式碼如下:

  1 public partial
class DllLoadForm : Form 2 { 3 public DllLoadForm() 4 { 5 InitializeComponent(); 6 } 7 8 9 10 private void btnOpenFile_Click(object sender, EventArgs e) 11 { 12 OpenFileDialog ofd = new OpenFileDialog()
13 { 14 Multiselect=false, 15 Filter = "Dll Info|*.dll|All Files|*.*", 16 InitialDirectory=AppDomain.CurrentDomain.BaseDirectory, 17 Title="Dll資訊", 18 Tag="請選擇" 19 }; 20 if (ofd.ShowDialog() == DialogResult.OK) { 21 this.txtDllFile.Text = ofd.FileName; 22 } 23 } 24 25 private void btnLoadDll_Click(object sender, EventArgs e) 26 { 27 if (string.IsNullOrEmpty(this.txtDllFile.Text.Trim())) { 28 MessageBox.Show("請選擇dll檔案"); 29 return; 30 } 31 LoadDllInfo(this.txtDllFile.Text); 32 } 33 34 /// <summary> 35 /// 動態載入Dll 36 /// </summary> 37 /// <param name="dllPath">需要載入的Dll的路徑</param> 38 public void LoadDllInfo(string dllPath) 39 { 40 if (File.Exists(dllPath)) 41 { 42 TreeNodeCollection tvNodes = tvDllInfo.Nodes; 43 tvNodes.Clear(); 44 tvNodes.Add("DllInfo"); 45 AssemblyName dllAssemblyName = AssemblyName.GetAssemblyName(dllPath); 46 Assembly dllAssembly = Assembly.Load(dllAssemblyName); 47 Module[] modules = dllAssembly.GetModules();//獲取作為程式集一部分的所有模組資訊 48 Type[] types = dllAssembly.GetTypes();//獲取程式集中定義的所有型別 49 AssemblyName[] referrenceAsseblies = dllAssembly.GetReferencedAssemblies();//獲取程式集引用的程式集資訊 50 tvNodes[0].Nodes.Add("基本資訊"); 51 52 string dllFullName = dllAssembly.FullName; 53 bool isGlobalAsseblyCache = dllAssembly.GlobalAssemblyCache;//是否從全域性程式集載入 54 bool isFullTrusted = dllAssembly.IsFullyTrusted;//是否已完全信任方式載入的 55 Module manifestModule = dllAssembly.ManifestModule;//獲取清單模組 56 bool isReflectionOnly = dllAssembly.ReflectionOnly;//是否載入到只反射模組中 57 //更新到節點 58 tvNodes[0].Nodes[0].Nodes.Add(string.Format("全路徑:{0}", dllFullName)); 59 tvNodes[0].Nodes[0].Nodes.Add(string.Format("是否全域性程式集:{0}", isGlobalAsseblyCache)); 60 tvNodes[0].Nodes[0].Nodes.Add(string.Format("是否全信任:{0}", isFullTrusted)); 61 tvNodes[0].Nodes[0].Nodes.Add(string.Format("是否只反射:{0}", isReflectionOnly)); 62 tvNodes[0].Nodes[0].Nodes.Add(string.Format("清單模組:{0}", manifestModule.Name)); 63 IEnumerable<Type> exportedTypes = dllAssembly.ExportedTypes;//公共型別集合 64 tvNodes[0].Nodes.Add("模組資訊"); 65 int i = 0; 66 foreach (var module in modules) 67 { 68 FieldInfo[] fields = module.GetFields();//返回模組中定義的全域性欄位 69 MethodInfo[] methods = module.GetMethods();//返回模組中定義的全域性方法 70 Type[] mtypes = module.GetTypes();//返回模組中定義的型別集合 71 bool isResource = module.IsResource();//指示此模組是否是資源 72 int mdStreamVersion = module.MDStreamVersion;//獲取源資料流的版本 73 Guid versionId = module.ModuleVersionId;//獲取模組的版本ID 74 string moduleName = module.Name;//獲取模組的名稱,去除路徑的 75 int metadataToken = module.MetadataToken; 76 string scopeName = module.ScopeName; 77 tvNodes[0].Nodes[1].Nodes.Add(string.Format("模組:{0}", moduleName)); 78 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("資料流版本:{0}", mdStreamVersion)); 79 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("是否資源:{0}", isResource)); 80 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("版本ID:{0}", versionId)); 81 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("MetaData:{0}", metadataToken)); 82 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("ScopeName:{0}", scopeName)); 83 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(GetNodes<FieldInfo>(fields, "公共欄位")); 84 tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(GetNodes<MethodInfo>(methods, "Mehods")); 85 //tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("Types:{0}", string.Join(",", mtypes.Select(p => p.Name)))); 86 i++; 87 } 88 tvNodes[0].Nodes.Add("型別資訊"); 89 i = 0; 90 foreach (var type in types) 91 { 92 TypeAttributes typeAttributes = type.Attributes;//與Type關聯的屬性 93 string typeFullName = type.FullName;//獲取型別的完全限定名稱 94 FieldInfo[] typeFields = type.GetFields();//獲取所有的公共欄位 95 EventInfo[] typeEvents = type.GetEvents();//獲取所有的 公共事件 96 Type[] typeInterfaces = type.GetInterfaces();//獲取所有的公共介面 97 MemberInfo[] typeMembers = type.GetMembers();//獲取所有的公共成員 98 MethodInfo[] typeMethods = type.GetMethods();//獲取所有的公共方法 99 TypeInfo typeInfo = type.GetTypeInfo();//返回指定型別的表述形式 100 string nameSpace = type.Namespace; //指定型別的名稱空間 101 string typeName = type.Name;//獲取當前成員的名稱 102 ConstructorInfo[] typeConstructors = type.GetConstructors();//型別的建構函式 103 tvNodes[0].Nodes[2].Nodes.Add(string.Format("型別:{0}", typeName)); 104 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(string.Format("全名稱:{0}", typeFullName)); 105 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(string.Format("制定型別名稱:{0}", typeInfo.Name)); 106 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(string.Format("名稱空間:{0}", nameSpace)); 107 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(string.Format("介面:{0}", string.Join(",", typeInterfaces.Select(p => p.Name)))); 108 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(GetNodes<FieldInfo>(typeFields, "公共欄位")); 109 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(GetNodes<ConstructorInfo>(typeConstructors, "建構函式")); 110 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(GetNodes<EventInfo>(typeEvents, "事件")); 111 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(GetNodes<MemberInfo>(typeMembers, "成員Member")); 112 tvNodes[0].Nodes[2].Nodes[i].Nodes.Add(GetNodes<MethodInfo>(typeMethods, "公共方法")); 113 i++; 114 115 } 116 } 117 } 118 119 /// <summary> 120 /// 通過型別獲取節點 121 /// </summary> 122 /// <typeparam name="T"></typeparam> 123 /// <param name="lstInfos"></param> 124 /// <param name="name"></param> 125 /// <returns></returns> 126 public TreeNode GetNodes<T>(T[] lstInfos, string name) where T : MemberInfo 127 { 128 TreeNode tNode = new TreeNode(name); 129 foreach (var t in lstInfos) 130 { 131 tNode.Nodes.Add(t.Name); 132 } 133 return tNode; 134 } 135 136 /// <summary> 137 /// 呼叫靜態方法的例子 138 /// </summary> 139 /// <param name="sender"></param> 140 /// <param name="e"></param> 141 private void btnCallStaticByReflection_Click(object sender, EventArgs e) 142 { 143 AssemblyName assemblyName = AssemblyName.GetAssemblyName("TestAssembly.exe"); 144 Assembly assembly = Assembly.Load(assemblyName); 145 Type t = assembly.GetType("TestAssembly.Program", true, true); 146 //object o= Activator.CreateInstance(t, false); 147 MethodInfo methodInfo = t.GetMethod("Main",BindingFlags.Static|BindingFlags.Public); 148 methodInfo.Invoke(null,new string[][] { new string[] { "g" } }); 149 150 } 151 152 /// <summary> 153 /// 呼叫非靜態方法的例子 154 /// </summary> 155 /// <param name="sender"></param> 156 /// <param name="e"></param> 157 private void btnCallFunctionByReflection_Click(object sender, EventArgs e) 158 { 159 AssemblyName assemblyName = AssemblyName.GetAssemblyName("TestAssembly.exe");//此處是相對路徑 160 Assembly assembly = Assembly.Load(assemblyName); 161 Type t = assembly.GetType("TestAssembly.Program", true, true); 162 object o = Activator.CreateInstance(t, false); 163 MethodInfo methodInfo = t.GetMethod("TestAssembly", BindingFlags.Instance|BindingFlags.Public); 164 object tmp= methodInfo.Invoke(o,null); 165 MessageBox.Show(tmp.ToString()); 166 } 167 }


----------------------------------------------------------------------

動態載入和反射呼叫的功能還有很多,不能一一列舉,只能在以後的工作中用到時再加以研究。

出處:https://www.cnblogs.com/hsiang/p/6505568.html

您的資助是我最大的動力!
金額隨意,歡迎來賞!
款後有任何問題請給我留言。

如果,您認為閱讀這篇部落格讓您有些收穫,不妨點選一下右下角的推薦按鈕。
如果,您希望更容易地發現我的新部落格,不妨點選一下綠色通道的關注我。(●'◡'●)

如果對你有所幫助,贊助一杯咖啡!打 付款後有任何問題請給我留言!!!

因為,我的寫作熱情也離不開您的肯定與支援,感謝您的閱讀,我是【Jack_孟】!