• .net学习之泛型、程序集和反射


    一、泛型
    1.CLR编译时,编译器只为MyList<T>类型产生“泛型版”的IL代码——并不进行泛型的实例化,T在中间只充当占位符。例如:MyList 类型元数据中显示的<T>

    2.执行的时候,当JIT编译器第一次遇到MyList<int>时,将用int替换“范型版”IL代码与元数据中的T—进行泛型类型的实例化。例如 :Main函数中显示的<int>

    3.什么是泛型
    泛型是具有占位符(类型参数)的类、方法、结构、接口

    4.泛型类的继承
    public class Father<K,V>{} //父类
    (1)定义子类时直接为父类泛型参数赋值
    public class Son : Father<int,string>
    (2)定义子类时把子类泛型参数赋给父类泛型参数
    public class Son<W,Y> : Father<W,Y>
    (3)定义子类时有子类泛型参数,同时为父类泛型参数赋值
    public class Son<W,Y> : Father<int,string>

    5.泛型约束
    (1)基类约束
    private class House<T1, T2> where T1 : Dog where T2 : Cat
    {

    }
    约束T1和T2必须继承Dog类和Cat类
    (2)接口约束
    class MyPetPlay<T, V> where T : IGetReward<T> where V : IWalk, ISing<V>
    {

    }
    (3)结构和类约束
    public class C<T> where T : struct
    {
    }
    public class C2<T> where T : class
    {
    }
    (4)构造函数约束
    class Pet<T> where T : new()//T类中必须有无参数的构造函数
    {
    T t;
    public Pet()
    {
    t = new T();
    }
    }

    6.泛型方法
    public int MethodName<T>(T param){...}
    public int MethodName<T,K>(T param,K param2){...}
    泛型方法 的泛型参数,可以用在该方法的 形参、方法体、返回值三处。

    什么是元数据?
    元数据(Metadata)描述了程序集的内容。通过将元数据嵌入每个程序集中,任何程序集都可以实现完全的自我描述,从而简化了发布使用较旧技术的组件时所需进行的工作。.NET使用元数据省略组件的注册过程。

    程序集就是包含IL和元数据的集合,即从源代码编译生成的。

    二、程序集和反射
    1.程序集
    我们所写的所有代码都会编译到程序集文件中,并在运行时以Assembly对象方式加载到内存中运行。
    运行时,类会加载到内存中就是Type对象,类的成员(方法、字段、属性、事件等)加载到内存中也有相应的对象
    2.反射
    在程序运行时,动态获取加载程序集、动态获取类型(如类、接口等)、动态获取类型的成员信息(如方法、字段、属性等),动态创建类型实例,以及调用和访问这些实例成员。

    Dog.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WindowsForms20140808
    {
        public class Dog
        {
            public string name;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            public int Age { get; set; }
            private bool gender;
    
            public string SayHi()
            {
                return this.Name + "," + this.Age + "," + this.gender;
            }
        }
    }
     private void button1_Click(object sender, EventArgs e)
            {
                Dog d = new Dog();
                d.Name = "旺旺";
                d.Age = 1;
                d.SayHi();
                //获取当前正在运行的程序集对象
                Assembly ass = this.GetType().Assembly;
                //获取程序集中的Dog类的类型对象 
                Type tDog = ass.GetType("WindowsForms20140808.Dog");
                //也可以通过typeOf获取
                //Type tDog = typeof (Dog);
    
                FieldInfo fInfo = tDog.GetField("name");
                PropertyInfo pInfo = tDog.GetProperty("Name");
                MethodInfo mInfo = tDog.GetMethod("SayHi");
                //根据Dog的Type对象,实例化一个Dog对象
                Dog d2 = Activator.CreateInstance<Dog>();
                //使用Dog类的name字段对象,为d2实例的name字段赋值
                fInfo.SetValue(d2, "小白");
    
                //调用对象私有成员
                FieldInfo fGender = tDog.GetField("gender", BindingFlags.NonPublic | BindingFlags.Instance);
                fGender.SetValue(d2, true);
                string strRes = mInfo.Invoke(d2, null).ToString();
    
    
                //获得当前 程序域中 所有的Assembly
                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                //获取当前正在运行的程序集对象
                Assembly ass1 = this.GetType().Assembly;
                //根据路径加载Assembly 
                Assembly ass2 = Assembly.LoadFrom("WindowsForms20140808.exe");
    
            }

     三、利用反射和特性实现一个简单的记事本插件

    1.实现记事本插件接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TextNotePlugsInterface
    {
        /// <summary>
        /// 记事本插件接口
        /// </summary>
        public interface IPlugs
        {
            /// <summary>
            /// 处理文本
            /// </summary>
            /// <param name="text"></param>
            /// <returns></returns>
            string ProcessText(string text);
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TextNotePlugsInterface
    {
       /// <summary>
       /// 菜单特性类
       /// </summary>
        public class MenuNameAttribute : Attribute
        {
            private string _name;
    
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
            public MenuNameAttribute(string name)
            {
                this._name = name;
            }
        }
    }

    2.实现具体的插件类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using TextNotePlugsInterface;
    
    namespace TextNotePlugs
    {
        [MenuName("转换为小写")]
        public class TextToLower:IPlugs
        {
            public string ProcessText(string text)
            {
                return text.ToLower();
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using TextNotePlugsInterface;
    
    namespace TextNotePlugs
    {
        [MenuName("转换为大写")]
        public class TextToUpper:IPlugs
        {
            public string ProcessText(string text)
            {
                return text.ToUpper();
            }
        }
    }

    3.新建记事本程序,并将生成的记事本插件dll放入记事本程序的plugs文件夹中

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Reflection;
    using TextNotePlugsInterface;
    
    namespace WindowsForms20140809
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //通过反射获取插件的dll文件
                string strPath = Path.GetDirectoryName(this.GetType().Assembly.Location) + "\plugs";
                string [] files =Directory.GetFiles(strPath,"*.dll");
                foreach (string file in files)
                {
                    Assembly ass = Assembly.LoadFrom(file);
                    //获取公开的类
                    Type[] types = ass.GetExportedTypes();
                    Type iplugsType = typeof (IPlugs);
                    foreach (Type type in types)
                    {
                        //判断type是否实现了IPlugs接口
                        if (iplugsType.IsAssignableFrom(type))
                        {
                            //获取类型的 MenuNameAttribute 特性对象,或将 内部的 Name属性值取出作为 按钮的文本
                            object[] attrs = type.GetCustomAttributes(typeof(MenuNameAttribute), false);
                            MenuNameAttribute menuAttr = attrs[0] as MenuNameAttribute;
                            IPlugs iplug = Activator.CreateInstance(type) as IPlugs;
                            //创建插件按钮
                            ToolStripMenuItem menuItem = new ToolStripMenuItem(menuAttr.Name);
                            this.记事本插件ToolStripMenuItem.DropDownItems.Add(menuItem);
                            menuItem.Click += menuItem_Click;
                            menuItem.Tag = iplug;
                        }
                    }
                }
    
    
            }
    
            void menuItem_Click(object sender, EventArgs e)
            {
                ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
                //从按钮中 取出 对应的 插件对象
                IPlugs iplug = menuItem.Tag as IPlugs;
                textBox1.Text = iplug.ProcessText(textBox1.Text);
            }
    
    
        }
    }
  • 相关阅读:
    java数据结构——哈希表(HashTable)
    java数据结构——红黑树(R-B Tree)
    java数据结构——二叉树(BinaryTree)
    java数据结构——递归(Recursion)例题持续更新中
    电路布线
    Cordova 入门
    mysql 分组加行号
    数据库表添加行号
    java jsp自定义标签
    java web Listener的简单使用案例
  • 原文地址:https://www.cnblogs.com/yxlblogs/p/3899951.html
Copyright © 2020-2023  润新知