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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM