C# 反射(Reflection)
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
优缺点
优点:
- 1、反射提高了程序的灵活性和扩展性。
- 2、降低耦合性,提高自适应能力。
- 3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
- 1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
- 2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。
假如我需要让代码自动识别并执行dll里面所有的方法,这个时候就可以用到c#反射;
1.先用C#写个简单的UI,效果图如下:
代码部分
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.Reflection;using System.Reflection.Emit;using System.Text.RegularExpressions;using System.Threading;namespace BojayUI{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void buttonOpenPort_Click(object sender, EventArgs e) { this.buttonClosePort.Enabled = true; this.buttonOpenPort.Enabled = false; this.buttonOpenProfile.Enabled = true; //this.buttonBojay.Enabled = true; MessageBox.Show("OpenPort finish!"); } private void buttonClosePort_Click(object sender, EventArgs e) { this.buttonClosePort.Enabled = false; this.buttonOpenPort.Enabled = true; this.buttonOpenProfile.Enabled = false; //this.buttonBojay.Enabled = false; MessageBox.Show("ClosePort finish!"); } private void buttonOpenFile_Click(object sender, EventArgs e) { OpenProfileDialog.InitialDirectory = "C:\\"; OpenProfileDialog.Filter = "Dynamic Link Library (*.dll)|*.dll|Text Document (*.txt)|*.txt|Comma-Separated Values (*.csv)|*.csv|All files (*.*)|*.*"; if (this.OpenProfileDialog.ShowDialog() == DialogResult.OK) { this.textBoxProfilePath.Text = OpenProfileDialog.FileName; //save the file…… //system.io.streamreader sr = new system.io.streamreader(openfiledialog1.filename); //this.textbox1.text = sr.readtoend(); //sr.close(); } } private void textBoxProfilePath_TextChanged(object sender, EventArgs e) { } private void button_start_Click(object sender, EventArgs e) { //******************执行所有类所有函数**************************// string path = this.textBoxProfilePath.Text; //string path = @"C:\Users\bojay\Desktop\ClassLibrary1\ClassLibrary1\bin\x86\Debug\ClassLibrary1.dll"; //加载dll文件 Assembly asm = Assembly.LoadFile(path); //正则表达式匹配 string pattern = @"\w*\."; Match match = Regex.Match(path, pattern); //string[] StrArray_dll = path.Split(new string[] { "\\" }, StringSplitOptions.None); //string StrArray_namespace = StrArray_dll[StrArray_dll.Length - 1]; //string[] String_class = StrArray_namespace.Split(new string[] { ".dl" }, StringSplitOptions.None); Type[] T = asm.GetTypes(); for (int i = 0; i < T.Length; i++) { //********************c#**************************** //Type type_1 = asm.GetType(T[i].Name); //string final_str = String_class[0] + "." + T[i].Name; string namespace_class = match.Value + T[i].Name; //获取类 Type type = asm.GetType(namespace_class); //创建该类的实例 object obj = Activator.CreateInstance(type); MethodInfo[] methods = type.GetMethods(); try { //c#:method.Length-4 //c++:method.Length-5 for (int index = 0; index < methods.Length - 4; index++) { MethodInfo mf = type.GetMethod(methods[index].Name); mf.Invoke(obj, null); //**************dll--function return value and parameters***************// //object result = mf.Invoke(obj, null); //Console.WriteLine(result); //ParameterInfo[] para = me.GetParameters(); } } catch (Exception ex) { throw ex; } } //****************************************************************// //****************************************************************// Type temp_type = asm.GetType(match.Value + T[0].Name); object temp_obj = Activator.CreateInstance(temp_type); //FieldInfo[] pi = temp_type.GetFields(); //get min FieldInfo Minlimit = temp_type.GetField("Minlimit"); string str_min = Minlimit.GetValue(temp_obj).ToString(); //get max FieldInfo Maxlimit = temp_type.GetField("Maxlimit"); string str_max = Maxlimit.GetValue(temp_obj).ToString(); //scope this.label_dll1scop.Text = str_min + " < X < " + str_max; //get target data string line; using (StreamReader sr = new StreamReader("common.txt")) { if ((line = sr.ReadLine()) != null) { this.label_dll1Data.Text = line; } } int MIN = Convert.ToInt32(str_min); int MAX = Convert.ToInt32(str_max); int Target = Convert.ToInt32(line); if (MIN < Target && Target < MAX) { this.label_dll1Result.BackColor = Color.Green; this.label_dll1Result.Text = "PASS"; } else { this.label_dll1Result.BackColor = Color.Red; this.label_dll1Result.Text = "Fail"; } //this.label_dll1scop.Text = "1.0 < X < 100.0"; //this.label_dll1Data.Text = "9.0"; //this.label_dll1Result.BackColor = Color.Green; //this.label_dll1Result.Text = "PASS"; //Console.ReadKey(); } }}
namespace BojayUI{ partial class Form1 { ////// Required designer variable. /// private System.ComponentModel.IContainer components = null; ////// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code ////// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.buttonOpenProfile = new System.Windows.Forms.Button(); this.textBoxProfilePath = new System.Windows.Forms.TextBox(); this.labelProfilePath = new System.Windows.Forms.Label(); this.buttonClosePort = new System.Windows.Forms.Button(); this.buttonOpenPort = new System.Windows.Forms.Button(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.button_start = new System.Windows.Forms.Button(); this.label_dll1scop = new System.Windows.Forms.Label(); this.label_dll1Data = new System.Windows.Forms.Label(); this.label_dll1Result = new System.Windows.Forms.Label(); this.label_dll1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.OpenProfileDialog = new System.Windows.Forms.OpenFileDialog(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.SuspendLayout(); // // tabControl1 // this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Location = new System.Drawing.Point(12, 38); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(776, 386); this.tabControl1.TabIndex = 0; // // tabPage1 // this.tabPage1.Controls.Add(this.buttonOpenProfile); this.tabPage1.Controls.Add(this.textBoxProfilePath); this.tabPage1.Controls.Add(this.labelProfilePath); this.tabPage1.Controls.Add(this.buttonClosePort); this.tabPage1.Controls.Add(this.buttonOpenPort); this.tabPage1.Location = new System.Drawing.Point(4, 22); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(768, 360); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Setting"; this.tabPage1.UseVisualStyleBackColor = true; // // buttonOpenProfile // this.buttonOpenProfile.Enabled = false; this.buttonOpenProfile.Location = new System.Drawing.Point(662, 73); this.buttonOpenProfile.Name = "buttonOpenProfile"; this.buttonOpenProfile.Size = new System.Drawing.Size(100, 23); this.buttonOpenProfile.TabIndex = 4; this.buttonOpenProfile.Text = "OpenProfile"; this.buttonOpenProfile.UseVisualStyleBackColor = true; this.buttonOpenProfile.Click += new System.EventHandler(this.buttonOpenFile_Click); // // textBoxProfilePath // this.textBoxProfilePath.Location = new System.Drawing.Point(132, 76); this.textBoxProfilePath.Name = "textBoxProfilePath"; this.textBoxProfilePath.Size = new System.Drawing.Size(502, 21); this.textBoxProfilePath.TabIndex = 3; this.textBoxProfilePath.TextChanged += new System.EventHandler(this.textBoxProfilePath_TextChanged); // // labelProfilePath // this.labelProfilePath.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192))))); this.labelProfilePath.Location = new System.Drawing.Point(6, 75); this.labelProfilePath.Name = "labelProfilePath"; this.labelProfilePath.Size = new System.Drawing.Size(100, 23); this.labelProfilePath.TabIndex = 2; this.labelProfilePath.Text = "ProfilePath"; this.labelProfilePath.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // buttonClosePort // this.buttonClosePort.Enabled = false; this.buttonClosePort.Location = new System.Drawing.Point(662, 6); this.buttonClosePort.Name = "buttonClosePort"; this.buttonClosePort.Size = new System.Drawing.Size(100, 23); this.buttonClosePort.TabIndex = 1; this.buttonClosePort.Text = "ClosePort"; this.buttonClosePort.UseVisualStyleBackColor = true; this.buttonClosePort.Click += new System.EventHandler(this.buttonClosePort_Click); // // buttonOpenPort // this.buttonOpenPort.Location = new System.Drawing.Point(6, 6); this.buttonOpenPort.Name = "buttonOpenPort"; this.buttonOpenPort.Size = new System.Drawing.Size(100, 23); this.buttonOpenPort.TabIndex = 0; this.buttonOpenPort.Text = "OpenPort"; this.buttonOpenPort.UseVisualStyleBackColor = true; this.buttonOpenPort.Click += new System.EventHandler(this.buttonOpenPort_Click); // // tabPage2 // this.tabPage2.Controls.Add(this.button_start); this.tabPage2.Controls.Add(this.label_dll1scop); this.tabPage2.Controls.Add(this.label_dll1Data); this.tabPage2.Controls.Add(this.label_dll1Result); this.tabPage2.Controls.Add(this.label_dll1); this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(768, 360); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Work"; this.tabPage2.UseVisualStyleBackColor = true; // // button_start // this.button_start.Location = new System.Drawing.Point(645, 273); this.button_start.Name = "button_start"; this.button_start.Size = new System.Drawing.Size(107, 73); this.button_start.TabIndex = 4; this.button_start.Text = "Start"; this.button_start.UseVisualStyleBackColor = true; this.button_start.Click += new System.EventHandler(this.button_start_Click); // // label_dll1scop // this.label_dll1scop.BackColor = System.Drawing.Color.Silver; this.label_dll1scop.Location = new System.Drawing.Point(514, 14); this.label_dll1scop.Name = "label_dll1scop"; this.label_dll1scop.Size = new System.Drawing.Size(238, 27); this.label_dll1scop.TabIndex = 3; this.label_dll1scop.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label_dll1Data // this.label_dll1Data.BackColor = System.Drawing.Color.Silver; this.label_dll1Data.Location = new System.Drawing.Point(326, 14); this.label_dll1Data.Name = "label_dll1Data"; this.label_dll1Data.Size = new System.Drawing.Size(182, 27); this.label_dll1Data.TabIndex = 2; this.label_dll1Data.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label_dll1Result // this.label_dll1Result.BackColor = System.Drawing.Color.Silver; this.label_dll1Result.Location = new System.Drawing.Point(242, 14); this.label_dll1Result.Name = "label_dll1Result"; this.label_dll1Result.Size = new System.Drawing.Size(78, 27); this.label_dll1Result.TabIndex = 1; this.label_dll1Result.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label_dll1 // this.label_dll1.BackColor = System.Drawing.Color.Silver; this.label_dll1.Location = new System.Drawing.Point(54, 14); this.label_dll1.Name = "label_dll1"; this.label_dll1.Size = new System.Drawing.Size(182, 27); this.label_dll1.TabIndex = 0; this.label_dll1.Text = "GetValue_FromDll1Text"; this.label_dll1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label1 // this.label1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); this.label1.Location = new System.Drawing.Point(12, 13); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(776, 13); this.label1.TabIndex = 1; this.label1.Text = "Bojay Common UI V1.0"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label2 // this.label2.Location = new System.Drawing.Point(12, 426); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(776, 23); this.label2.TabIndex = 2; this.label2.Text = "Developed by Tony"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // OpenProfileDialog // this.OpenProfileDialog.FileName = "OpenProfileDialog"; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoValidate = System.Windows.Forms.AutoValidate.Disable; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.tabControl1); this.Name = "Form1"; this.Text = "DEMO_UI"; this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabPage1.PerformLayout(); this.tabPage2.ResumeLayout(false); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Button buttonOpenPort; private System.Windows.Forms.Button buttonClosePort; private System.Windows.Forms.Button buttonOpenProfile; private System.Windows.Forms.TextBox textBoxProfilePath; private System.Windows.Forms.Label labelProfilePath; private System.Windows.Forms.OpenFileDialog OpenProfileDialog; private System.Windows.Forms.Label label_dll1; private System.Windows.Forms.Label label_dll1scop; private System.Windows.Forms.Label label_dll1Data; private System.Windows.Forms.Label label_dll1Result; private System.Windows.Forms.Button button_start; }}
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace BojayUI{ static class Program { ////// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }}
2.C#写个dll
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.IO;namespace ClassLibrary1{ public class Common { public int Maxlimit = 99; public int Minlimit = 1; public int common = 0; } public class Class1:Common { public void WriteFile() { int temp = this.common+5; using (StreamWriter sw = new StreamWriter("common.txt")) { sw.WriteLine(temp); } } }}
3.运行UI,加载dll路径
4.执行dll所有类里面的所有方法和属性
5.结果pass,说明该dll里面的函数功能运行结果达到我们的要求;当然啦,这个dll里面只是简单的通过文件写读,将某个目标值进行判断而已,而且我们还需要定义某个公用的类Common,及对应公用属性Maxlimit、Minlimit、common
总结:
<1>dll的C#代码里的namespace命名空间必须和dll文件名一致,因为我们进行匹配的时候只是匹配dll文件名;当然,我们也可以有更好的方法,例如将dll命名空间保持不变,这样我们还不需要对dll路径进行解析
<2>解析字符串的方式可以用正则,也可以用split等较为通俗简便的方法,但可能步骤会稍微多点,建议能用正则还是用正则
<3>dll是用C#写的,可以考虑能否写个.net 平台的C++dll