C#中通过反射方法获取控件类型和名称
这个方法是简单的也是神奇的。
有木有想过,将自己项目中的所有类型,包括自定义类型的命名空间和名称全部获取出来?
有木有想过,有一种简便的方法可以自动化管理项目中的控件和窗体?
有木有想过...
首先,要敢想、要敢尝试。
通过以下方法,进行简单变换,是可以做到本程序控制本项目的窗体和控件。
以下方法简单了,就不一一说明了,如果你觉得有用,全部复制了编译一下,看看就明白是怎么反射了。
当然懂得大大们看到我有不足之处,请不要谩骂了,我脸皮薄,被你们骂骂就泄气了,技术有限,请大大们不吝赐教。
基础方法
通过反射获取项目中所有类型(重点)
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace BackgroundManager.Func { public class GetAssemblyClass { static Type[] _assemblyArray; readonly static Object lockObject = new Object(); public Type[] GetAssembly() { if (_assemblyArray == null) { lock (lockObject) { _assemblyArray = Assembly.GetExecutingAssembly().GetTypes(); } } return _assemblyArray; } public Type[] GetFormAssembly() { Type[] assemblyArray = GetAssembly(); string allType = typeof(Form).FullName; string mainType = typeof(frmMain).FullName; return Array.FindAll(assemblyArray, delegate(Type type) { return (type.BaseType.FullName == allType && type.FullName != mainType); }); } public Type[] GetUserCtlAssembly() { Type[] assemblyArray = GetAssembly(); string allType = typeof(UserControl).FullName; string mainType = typeof(frmMain).FullName; return Array.FindAll(assemblyArray, delegate(Type type) { return (type.BaseType.FullName == allType && type.FullName != mainType); }); } } }
图像相关帮助类
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Microsoft.Win32; namespace BackgroundManager.Func { public class SystemIconHelper { [DllImport("shell32.dll")] public static extern uint ExtractIconEx(string lpszFile, int nIconIndex, int[] phiconLarge, int[] phiconSmall, uint nIcons); [DllImport("gdi32.dll")] private static extern bool DeleteObject(IntPtr hObject); public static Dictionary<String, Icon> IconList = new Dictionary<String, Icon>(); /// <summary> /// Image转换为Icon /// </summary> /// <param name="orgImg"></param> /// <returns></returns> public static Icon ImageToIcon(Image orgImg) { var bmp = new Bitmap(orgImg); IntPtr h = bmp.GetHicon(); Icon icon = Icon.FromHandle(h); // 释放IntPtr DeleteObject(h); return icon; } /// <summary> /// Image 转化为 字节流 /// </summary> /// <param name="image"></param> /// <param name="Format"></param> /// <returns></returns> public static byte[] ImageToByteArray(Image image, ImageFormat Format) { var ms = new MemoryStream(); image.Save(ms, ImageFormat.Png); return ms.ToArray(); } /// <summary> /// 字节流 转化为 Image /// </summary> /// <param name="btArray"></param> /// <returns></returns> public static Image ImageFromByteArray(byte[] btArray) { var ms = new MemoryStream(btArray); Image returnImage = Image.FromStream(ms); return returnImage; } /// <summary> /// 获取文件内容的类型 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static string GetContentType(string fileName) { string contentType = "application/octetstream"; try { string ext = Path.GetExtension(fileName).ToLower(); RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(ext); if (registryKey != null && registryKey.GetValue("Content Type") != null) contentType = registryKey.GetValue("Content Type").ToString(); } catch (Exception) { } return contentType; } /// <summary> /// 根据文件的类型获取 Icon /// </summary> /// <param name="sFileExt"></param> /// <returns></returns> public static Icon GetIconByFileType(String sFileExt) { string sProg = Registry.ClassesRoot.OpenSubKey(Registry.ClassesRoot.OpenSubKey(sFileExt).GetValue(String.Empty).ToString()) .OpenSubKey("shell") .OpenSubKey("open") .OpenSubKey("command") .GetValue(String.Empty) .ToString(); sProg = sProg.Substring(0, 1) == Convert.ToChar(34).ToString() ? sProg.Substring(1, sProg.IndexOf(Convert.ToChar(34), 2) - 1) : sProg.Substring(0, sProg.IndexOf(" ", 2)); sProg = sProg.Replace("%1", String.Empty); Icon oIcon = Icon.ExtractAssociatedIcon(sProg); return oIcon; } /// <summary> /// 根据文件名获得图片数组下标 /// </summary> /// <param name="fileName"></param> /// <param name="isLarge"></param> /// <returns></returns> public static Icon GetIconByFileName(String fileName, bool isLarge) { String GetIcon = new FileInfo(fileName).Extension; if (IconList.ContainsKey(GetIcon)) { return IconList[GetIcon]; } Icon mIcon = GetIconByFileType(GetIcon, isLarge); if (mIcon != null) { IconList.Add("GetIcon", mIcon); return mIcon; } return null; } /// <summary> /// 给出文件扩展名(.*),返回相应图标 /// 若不以"."开头则返回文件夹的图标。 /// </summary> /// <param name="fileType"></param> /// <param name="isLarge"></param> /// <returns></returns> public static Icon GetIconByFileType(string fileType, bool isLarge) { if (!string.IsNullOrEmpty(fileType)) { string regIconString = null; //默认指定为文件夹图标 string systemDirectory = Environment.SystemDirectory + "\\shell32.dll,3"; if (fileType[0] == '.') { //读系统注册表中文件类型信息 RegistryKey regVersion = Registry.ClassesRoot.OpenSubKey(fileType, true); if (regVersion != null) { string regFileType = regVersion.GetValue(String.Empty) as String; regVersion.Close(); regVersion = Registry.ClassesRoot.OpenSubKey(regFileType + @"\DefaultIcon", true); if (regVersion != null) { regIconString = regVersion.GetValue(String.Empty) as String; regVersion.Close(); } } if (regIconString == null) { //没有读取到文件类型注册信息,指定为未知文件类型的图标 regIconString = systemDirectory + "shell32.dll,0"; } } String[] fileIcon = regIconString.Split(new[] { ',' }); if (fileIcon.Length != 2) { //系统注册表中注册的标图不能直接提取,则返回可执行文件的通用图标 fileIcon = new[] { systemDirectory + "shell32.dll", "2" }; } Icon resultIcon = null; try { //调用API方法读取图标 var phiconLarge = new int[1]; var phiconSmall = new int[1]; ExtractIconEx(fileIcon[0], Int32.Parse(fileIcon[1]), phiconLarge, phiconSmall, 1); var IconHnd = new IntPtr(isLarge ? phiconLarge[0] : phiconSmall[0]); resultIcon = Icon.FromHandle(IconHnd); } catch { try { //第二方案 resultIcon = GetIconByFileType(fileType); } catch { //默认方案 regIconString = systemDirectory + "shell32.dll,0"; fileIcon = regIconString.Split(new[] { ',' }); resultIcon = null; //调用API方法读取图标 var phiconLarge = new int[1]; var phiconSmall = new int[1]; ExtractIconEx(fileIcon[0], Int32.Parse(fileIcon[1]), phiconLarge, phiconSmall, 1); var IconHnd = new IntPtr(isLarge ? phiconLarge[0] : phiconSmall[0]); resultIcon = Icon.FromHandle(IconHnd); } } return resultIcon; } return null; } } }
自定义属性的类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BackgroundManager { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class MyAttribute : Attribute { private string _name = ""; private string _display = ""; private string _value = ""; public MyAttribute(string name, string value, string display) { _name = name; _value = value; _display = display; } public string Value { get { return _value; } set { _value = value; } } public string Display { get { return _display; } set { _display = value; } } public string Name { get { return _name; } set { _name = value; } } } }
frmMain主窗体
Application.Run(new frmMain()); 为了减少篇幅,就没写这个,但它作为主窗体启动。
mainTree 上的节点是通过反射获取到所有控件和窗体,然后将它们加入到mainTree中
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 BackgroundManager.Func; namespace BackgroundManager { public partial class frmMain : Form { public frmMain() { InitializeComponent(); this.IsMdiContainer = true; InitTreeList(); } private void InitTreeList() { GetAssemblyClass getass = new GetAssemblyClass(); Type[] frmTypes = getass.GetFormAssembly(); Type[] ctlTypes = getass.GetUserCtlAssembly(); mainTree.Nodes.Clear(); var typeArray = new List<Type>(); typeArray.AddRange(frmTypes); typeArray.AddRange(ctlTypes); foreach (Type type in typeArray) { TreeNode node; string name = type.Name; MyAttribute[] customAttributes = type.GetCustomAttributes(typeof(MyAttribute), true) as MyAttribute[]; if (customAttributes != null && customAttributes.Length > 0) { name = customAttributes[0].Display; } node = new TreeNode(name); node.Tag = type; mainTree.Nodes.Add(node); } } private void mainTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { } private void mainTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node != null) { Type t = e.Node.Tag as Type; if (t != null) { UserControl c = Activator.CreateInstance(t) as UserControl; if (c != null) { this.splitContainer1.Panel2.Controls.Clear(); this.splitContainer1.Panel2.Controls.Add(c); c.Dock = DockStyle.Fill; } Form c2 = Activator.CreateInstance(t) as Form; if (c2 != null) { c2.MdiParent = this; this.splitContainer1.Panel2.Controls.Clear(); this.splitContainer1.Panel2.Controls.Add(c2); c2.Dock = DockStyle.Fill; c2.Show(); } } } } /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows 窗体设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.mainTree = new System.Windows.Forms.TreeView(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.SuspendLayout(); this.SuspendLayout(); // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitContainer1.Location = new System.Drawing.Point(0, 0); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 // this.splitContainer1.Panel1.AutoScroll = true; this.splitContainer1.Panel1.Controls.Add(this.mainTree); // // splitContainer1.Panel2 // this.splitContainer1.Panel2.AutoScroll = true; this.splitContainer1.Size = new System.Drawing.Size(524, 391); this.splitContainer1.SplitterDistance = 178; this.splitContainer1.TabIndex = 1; // // mainTree // this.mainTree.Dock = System.Windows.Forms.DockStyle.Fill; this.mainTree.Location = new System.Drawing.Point(0, 0); this.mainTree.Name = "mainTree"; this.mainTree.Size = new System.Drawing.Size(178, 391); this.mainTree.TabIndex = 0; this.mainTree.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.mainTree_NodeMouseClick); this.mainTree.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.mainTree_NodeMouseDoubleClick); // // frmMain // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.BackColor = System.Drawing.SystemColors.Control; this.ClientSize = new System.Drawing.Size(524, 391); this.Controls.Add(this.splitContainer1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "frmMain"; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "后台管理"; this.splitContainer1.Panel1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); this.ResumeLayout(false); } #endregion private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.TreeView mainTree; } }
请注意 this.IsMdiContainer = true;
以下四个类为测试控件
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace BackgroundManager.GUI { [MyAttribute("","","test1")] public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(52, 49); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(41, 12); this.label1.TabIndex = 0; this.label1.Text = "label1"; // // UserControl1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.label1); this.Name = "UserControl1"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace BackgroundManager.GUI { public partial class UserControl3 : UserControl { public UserControl3() { InitializeComponent(); } /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(39, 29); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.UseVisualStyleBackColor = true; // // UserControl3 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.button1); this.Name = "UserControl3"; this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button button1; } }
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; namespace BackgroundManager.GUI { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.checkBox1 = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // checkBox1 // this.checkBox1.AutoSize = true; this.checkBox1.Location = new System.Drawing.Point(98, 37); this.checkBox1.Name = "checkBox1"; this.checkBox1.Size = new System.Drawing.Size(78, 16); this.checkBox1.TabIndex = 0; this.checkBox1.Text = "checkBox1"; this.checkBox1.UseVisualStyleBackColor = true; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 262); this.ControlBox = false; this.Controls.Add(this.checkBox1); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.CheckBox checkBox1; } }
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; namespace BackgroundManager.GUI { public partial class Form2 : Form { public Form2() { InitializeComponent(); } /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(94, 63); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.UseVisualStyleBackColor = true; // // Form2 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 262); this.Controls.Add(this.button1); this.Name = "Form2"; this.Text = "Form2"; this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button button1; } }
生成后运行界面:
这里我们选择的是userControl1,为什么在mainTree中显示的是test1,请仔细看UserControl1中的这段: [MyAttribute("","","test1")],这样可以灵活方便控制控件名称
做一个快乐的程序员