.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);

        }





    }

}

 

你可能感兴趣的:(.net)