zoukankan      html  css  js  c++  java
  • 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);
                });
            }
        }
    }
    GetAssemblyClass

    图像相关帮助类

    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;
            }
    
        }
    }
    SystemIconHelper

    自定义属性的类

    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; }
            }
        }
    }
    MyAttribute

    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;
    
        }
    }
    frmMain

     请注意  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;
        }
    }
    UserControl1

    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;
        }
    }
    UserControl3

    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;
        }
    }
    Form1

    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;
        }
    }
    Form2

    生成后运行界面:

    这里我们选择的是userControl1,为什么在mainTree中显示的是test1,请仔细看UserControl1中的这段:    [MyAttribute("","","test1")],这样可以灵活方便控制控件名称


    做一个快乐的程序员

  • 相关阅读:
    5_添加购物车 View+Con
    5_添加购物车 B+M
    5_添加购物车 D
    登录注册V
    bootstrap-标题
    h5整理--详解css的相对定位和绝对定位
    各大门户网站的css初始化代码
    九月二十八JS验证
    js函数和运算符
    4.1原始表达式 9/16
  • 原文地址:https://www.cnblogs.com/preacher/p/4165414.html
Copyright © 2011-2022 走看看