C#反射原理解析

反射

1. 程序集里的元数据

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64\ildasm.exe
用这个工具打开一个assembly。
file -> dump -> dump metainfo, 保存到dump.txt中, 看这个文件。
编译生成il代码,和类的metainfo。

AppDomain

一个程序运行起来以后,有一个AppDomain,在这个AppDomain中放了我们用到的所有assembly。

需要using System.Reflection;

Assembly的组成


2. 反射

反射概念:

在程序运行时,动态获取 程序集, 类型(class,interface)和类型的成员信息(方法,字段,属性等)。
在程序运行时,动态创建 类型实例, 以及调用和方法 动态创建出来的 类型实例的成员。
反射的应用:框架(Spring .net/ .Net MVC等)
在程序运行时,动态获取 程序集:

[csharp] view plain copy
print ?
  1. class Program  
  2. {  
  3.     static void Main(string[] args)  
  4.     {  
  5.         Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();  
  6.         Person p = new Person();  
  7.         p.TestAssembly();  
  8.     }  
  9. }  
  10.   
  11.   
  12. class Person {  
  13.     public String Name { getset; }  
  14.     public int Age { getset; }  
  15.     private int id;  
  16.   
  17.     public void TestAssembly() {  
  18.         Assembly ass = this.GetType().Assembly;  
  19.         Type[] types = ass.GetTypes();  
  20.         Type currentType = ass.GetType();  
  21.         //根据类的full name,获取在内存中的类型对象  
  22.         Type typeByFullName = ass.GetType("ConsoleApplication6.Person");  
  23.   
  24.   
  25.         Type type = this.GetType();  
  26.         MethodInfo[] methods = this.GetType().GetMethods();  
  27.         this.GetType().GetMembers();  
  28.         this.GetType().GetMember("Name");  
  29.         FieldInfo field =  type.GetField("id");  
  30.         PropertyInfo prop = type.GetProperty("Name");  
  31.   
  32.   
  33.     }  
  34. }  
    class Program
    {
        static void Main(string[] args)
        {
            Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
            Person p = new Person();
            p.TestAssembly();
        }
    }


    class Person {
        public String Name { get; set; }
        public int Age { get; set; }
        private int id;

        public void TestAssembly() {
            Assembly ass = this.GetType().Assembly;
            Type[] types = ass.GetTypes();
            Type currentType = ass.GetType();
            //根据类的full name,获取在内存中的类型对象
            Type typeByFullName = ass.GetType("ConsoleApplication6.Person");


            Type type = this.GetType();
            MethodInfo[] methods = this.GetType().GetMethods();
            this.GetType().GetMembers();
            this.GetType().GetMember("Name");
            FieldInfo field =  type.GetField("id");
            PropertyInfo prop = type.GetProperty("Name");


        }
    }
在程序运行时,动态创建 类型实例:在Person类中加下面4个方法,在Main中测试
[csharp] view plain copy
print ?
  1. public void CreatePersonObject() {  
  2.     Type type = this.GetType();  
  3.     //使用Person类的Type对象,创建一个Person对象  
  4.     Person p = Activator.CreateInstance(type) as Person;  
  5.     Person p1 = Activator.CreateInstance<Person>();  
  6.   
  7.     //使用Person类的Name属性对象,为p的Name属性赋值  
  8.     PropertyInfo prop = type.GetProperty("Name");  
  9.     prop.SetValue(p1, "toto");  
  10.     Console.WriteLine(p1.Name);  
  11.   
  12.     //使用Person类的Sayhi方法对象,调用p1的Sayhi方法  
  13.     MethodInfo method = type.GetMethod("Sayhi");  
  14.     method.Invoke(p1, null);  
  15.     MethodInfo method1 = type.GetMethod("ShowNumber");  
  16.     object[] arrParams = {2};  
  17.     method1.Invoke(p1, arrParams);  
  18.     MethodInfo method2 = type.GetMethod("GetString");  
  19.     String retStr = method2.Invoke(p1, null).ToString();  
  20.     Console.WriteLine(retStr);  
  21. }  
  22.   
  23. public void Sayhi() {  
  24.     Console.WriteLine("Hiiiiii");  
  25. }  
  26.   
  27. public void ShowNumber(int no) {  
  28.     Console.WriteLine(no);  
  29. }  
  30.   
  31. public String GetString() {  
  32.     return "Hello";  
  33. }  
        public void CreatePersonObject() {
            Type type = this.GetType();
            //使用Person类的Type对象,创建一个Person对象
            Person p = Activator.CreateInstance(type) as Person;
            Person p1 = Activator.CreateInstance<Person>();

            //使用Person类的Name属性对象,为p的Name属性赋值
            PropertyInfo prop = type.GetProperty("Name");
            prop.SetValue(p1, "toto");
            Console.WriteLine(p1.Name);

            //使用Person类的Sayhi方法对象,调用p1的Sayhi方法
            MethodInfo method = type.GetMethod("Sayhi");
            method.Invoke(p1, null);
            MethodInfo method1 = type.GetMethod("ShowNumber");
            object[] arrParams = {2};
            method1.Invoke(p1, arrParams);
            MethodInfo method2 = type.GetMethod("GetString");
            String retStr = method2.Invoke(p1, null).ToString();
            Console.WriteLine(retStr);
        }

        public void Sayhi() {
            Console.WriteLine("Hiiiiii");
        }

        public void ShowNumber(int no) {
            Console.WriteLine(no);
        }

        public String GetString() {
            return "Hello";
        }

在Main中
[csharp] view plain copy
print ?
  1. Person p = new Person();  
  2. p.CreatePersonObject();  
            Person p = new Person();
            p.CreatePersonObject();

3. Assembly 程序集对象

Assembly 是一个抽象类,我们用的都是RuntimeAssembly的对象。

获得程序集的方式:

  • 获得当前程序域中的所有程序集
    • Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
    • 所有用到过得aessembly。如果只是add ref了,没有在程序中用到,AppDomain.CurrentDomain.GetAssemblies()中没有。用到时才被JIT加载到内存。
    • 每个app都有一个AppDomain,OS不允许其他app访问这个程序的AppDomain
  • 获得当前对象所属的类所在的程序集
    • this.GetType().Assembly;
    • Type对象肯定在一个assembly对象中
    • 可以通过Type对象得到程序集。
  • 根据路径加载程序集
    • Assembly.LoadFrom(assPath);
    • [csharp] view plain copy
      print ?
      1. static void LoadAssemblyTest() {  
      2.     Assembly ass1 = Assembly.LoadFrom(@"c:\users\xcao\documents\visual studio 2012\Projects\ConsoleApplication6\ConsoleApplication6\libs\Ecole.dll");  
      3.     Type[] allTypes = ass1.GetTypes();  
      4.     //GetType的参数一定要是full name的string  
      5.     Type tStu = ass1.GetType("Ecole.Student");  
      6.     object stu1 = Activator.CreateInstance(tStu);  
      7. }  
              static void LoadAssemblyTest() {
                  Assembly ass1 = Assembly.LoadFrom(@"c:\users\xcao\documents\visual studio 2012\Projects\ConsoleApplication6\ConsoleApplication6\libs\Ecole.dll");
                  Type[] allTypes = ass1.GetTypes();
                  //GetType的参数一定要是full name的string
                  Type tStu = ass1.GetType("Ecole.Student");
                  object stu1 = Activator.CreateInstance(tStu);
              }


4. Type 类型对象

Type 是一个抽象类,我们用的都是TypeInfo类的对象。

程序运行时,一个class对应一个Type类的对象。通过Type对象可以获得类的所有信息。

获得Type对象的方式:

  • 通过类获得对应的Type
    • Type t1 = typeof(Person);
  • 通过对象获得Type
    • Type t2 = person.GetType();  this.GetType();
  • 用assembly对象,通过类的full name类获得type对象
    • [csharp] view plain copy
      print ?
      1. Assembly ass1 = Assembly.LoadFrom(@"c:\users\xcao\documents\visual studio 2012\Projects\ConsoleApplication6\ConsoleApplication6\libs\Ecole.dll");  
      2.   
      3. //GetType的参数一定要是full name的string  
      4. Type tStu = ass1.GetType("Ecole.Student");  
      5. object stu1 = Activator.CreateInstance(tStu);  
                  Assembly ass1 = Assembly.LoadFrom(@"c:\users\xcao\documents\visual studio 2012\Projects\ConsoleApplication6\ConsoleApplication6\libs\Ecole.dll");
                  
                  //GetType的参数一定要是full name的string
                  Type tStu = ass1.GetType("Ecole.Student");
                  object stu1 = Activator.CreateInstance(tStu);

  • 获得程序集中定义的所有的public类
    • Type[] allPublicTypes = ass1.GetExportedTypes();
  • 获得程序集中定义的所有的类
    • Type[] allTypes = ass1.GetTypes();

Type类的属性:

    • t.Assembly; 获取t所在的程序集
    • t.FullName; 获取t所对应的类的full name
    • t.Name; 获取t所对应的类的 name
    • t.IsArray; 判断t是否是一个数组类
    • t.IsEnum; 判断t是否是一个枚举类
    • t.IsAbstract; 判断t是否是一个抽象类
    • t.IsInterface; 判断t是否是一个interface

Type类的方法:

    • notebookInterfaceType.IsAssignableFrom(Type t);判断t是否实现了 notebookInterfaceType 接口
    • t.IsSubclassOf(Type parent); t是否是parent的子类
    • t.IsInstanceOfType(object o); o是否是t类的对象
    • t.GetFields();  //method, property 得到所有的public的fields,methods,properties
    •  t.GetField("gender"); 根据名字得到某个field
Type类的示例1:
[csharp] view plain copy
print ?
  1. static void TypeTest1() {  
  2.     Person p = new Person { Name = "toto", Age = 5};  
  3.     Type tPerson = p.GetType();  
  4.     PropertyInfo[] props = tPerson.GetProperties();  
  5.     StringBuilder builder = new StringBuilder(30);  
  6.     foreach (PropertyInfo prop in props)  
  7.     {  
  8.         builder.Append(prop.Name + "=" + prop.GetValue(p) + "\n");  
  9.     }  
  10.   
  11.     builder.Append("------------------------------- \n");  
  12.     FieldInfo[] fields = tPerson.GetFields();  
  13.     foreach(FieldInfo f in fields){  
  14.         builder.Append(f.Name + "=" + f.GetValue(p) + "\n");  
  15.     }  
  16.     Console.WriteLine(builder);  
  17. }  
        static void TypeTest1() {
            Person p = new Person { Name = "toto", Age = 5};
            Type tPerson = p.GetType();
            PropertyInfo[] props = tPerson.GetProperties();
            StringBuilder builder = new StringBuilder(30);
            foreach (PropertyInfo prop in props)
            {
                builder.Append(prop.Name + "=" + prop.GetValue(p) + "\n");
            }

            builder.Append("------------------------------- \n");
            FieldInfo[] fields = tPerson.GetFields();
            foreach(FieldInfo f in fields){
                builder.Append(f.Name + "=" + f.GetValue(p) + "\n");
            }
            Console.WriteLine(builder);
        }
Type类的示例2:
[csharp] view plain copy
print ?
  1. static void TypeTest2()  
  2. {  
  3.     Person p = new Person();  
  4.     Type tPerson = p.GetType();  
  5.     PropertyInfo f = tPerson.GetProperty("Name");  
  6.     f.SetValue(p, "titi");  
  7.     Console.WriteLine(p.Name);  
  8.   
  9. }  
        static void TypeTest2()
        {
            Person p = new Person();
            Type tPerson = p.GetType();
            PropertyInfo f = tPerson.GetProperty("Name");
            f.SetValue(p, "titi");
            Console.WriteLine(p.Name);

        }
Type类的示例3:
[csharp] view plain copy
print ?
  1. static void TypeTest3()  
  2. {  
  3.     Person p = new Person();  
  4.     Type tPerson = p.GetType();  
  5.     //所有的public方法  
  6.     MethodInfo[] methodsPublic = tPerson.GetMethods();  
  7.     //为了获取返回值,必须指定 BindingFlags.Instance 或 BindingFlags.Static。  
  8.     //public 的 static 的方法  
  9.     MethodInfo[] methodsPublicStatic = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Static);  
  10.     //public 的 实例方法  
  11.     MethodInfo[] methodsPublicInstance = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Instance);  
  12.     //只是在类中定义的(不包括继承的)public的 实例的 和static的 方法  
  13.     MethodInfo[] methodsPublicDeclareOnly = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Instance| BindingFlags.DeclaredOnly | BindingFlags.Static);  
  14. }  
        static void TypeTest3()
        {
            Person p = new Person();
            Type tPerson = p.GetType();
            //所有的public方法
            MethodInfo[] methodsPublic = tPerson.GetMethods();
            //为了获取返回值,必须指定 BindingFlags.Instance 或 BindingFlags.Static。
            //public 的 static 的方法
            MethodInfo[] methodsPublicStatic = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Static);
            //public 的 实例方法
            MethodInfo[] methodsPublicInstance = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            //只是在类中定义的(不包括继承的)public的 实例的 和static的 方法
            MethodInfo[] methodsPublicDeclareOnly = tPerson.GetMethods(BindingFlags.Public | BindingFlags.Instance| BindingFlags.DeclaredOnly | BindingFlags.Static);
        }

Type类示例4:
[csharp] view plain copy
print ?
  1. static void TypeTest4()  
  2. {  
  3.     Person person = new Person();  
  4.     Type tPerson = person.GetType();  
  5.     //得到所有的共有构造函数  
  6.     ConstructorInfo[] constructors = tPerson.GetConstructors();  
  7.     foreach (var ctor in constructors)  
  8.     {  
  9.         //Name都是 .ctor  
  10.         Console.WriteLine(ctor.Name);  
  11.         //构造函数的参数个数  
  12.         Console.WriteLine(ctor.GetParameters().Length);  
  13.         ParameterInfo[] parametres = ctor.GetParameters();  
  14.         foreach (var p in parametres)  
  15.         {  
  16.             Console.WriteLine(p.Name + " : " + p.ParameterType);  
  17.         }  
  18.     }  
  19.   
  20.     Person person1, person2;  
  21.   
  22.     // 调用指定参数的 构造函数 创建对象  
  23.     ConstructorInfo c1 = tPerson.GetConstructor(new Type[2] { typeof(String), typeof(int) });  
  24.     if(c1 != null){  
  25.         //通过构造函数的invoke方法来创建对象, 创建出来的对象 是invoke方法的返回值(object类型)  
  26.          person1 = c1.Invoke(new object[] { "toto", 2 }) as Person;  
  27.     }  
  28.   
  29.     // 调用无参数的构造函数 创建对象  
  30.     ConstructorInfo c2 = tPerson.GetConstructor(new Type[0]);  
  31.     if (c2 != null)  
  32.     {  
  33.          person2 = c2.Invoke(nullas Person;  
  34.     }  
  35.   
  36.     // 没有一个参数为String的构造函数, 返回null  ==>  c3为null  
  37.     ConstructorInfo c3 = tPerson.GetConstructor(new Type[] { typeof(String)});  
  38. }  
        static void TypeTest4()
        {
            Person person = new Person();
            Type tPerson = person.GetType();
            //得到所有的共有构造函数
            ConstructorInfo[] constructors = tPerson.GetConstructors();
            foreach (var ctor in constructors)
            {
                //Name都是 .ctor
                Console.WriteLine(ctor.Name);
                //构造函数的参数个数
                Console.WriteLine(ctor.GetParameters().Length);
                ParameterInfo[] parametres = ctor.GetParameters();
                foreach (var p in parametres)
                {
                    Console.WriteLine(p.Name + " : " + p.ParameterType);
                }
            }

            Person person1, person2;

            // 调用指定参数的 构造函数 创建对象
            ConstructorInfo c1 = tPerson.GetConstructor(new Type[2] { typeof(String), typeof(int) });
            if(c1 != null){
                //通过构造函数的invoke方法来创建对象, 创建出来的对象 是invoke方法的返回值(object类型)
                 person1 = c1.Invoke(new object[] { "toto", 2 }) as Person;
            }

            // 调用无参数的构造函数 创建对象
            ConstructorInfo c2 = tPerson.GetConstructor(new Type[0]);
            if (c2 != null)
            {
                 person2 = c2.Invoke(null) as Person;
            }

            // 没有一个参数为String的构造函数, 返回null  ==>  c3为null
            ConstructorInfo c3 = tPerson.GetConstructor(new Type[] { typeof(String)});
        }

通过反射调用类的私有成员

[csharp] view plain copy
print ?
  1. static void TypeTest5() {  
  2.     Person person = new Person();  
  3.     Type tPerson = person.GetType();  
  4.     MethodInfo privateMethod =  tPerson.GetMethod("TestPrivateMethod", BindingFlags.Instance | <span style="background-color: rgb(255, 255, 153);">BindingFlags.NonPublic</span>);  
  5.     privateMethod.Invoke(person, null);  
  6. }  
        static void TypeTest5() {
            Person person = new Person();
            Type tPerson = person.GetType();
            MethodInfo privateMethod =  tPerson.GetMethod("TestPrivateMethod", BindingFlags.Instance | <span style="background-color: rgb(255, 255, 153);">BindingFlags.NonPublic</span>);
            privateMethod.Invoke(person, null);
        }
类中的public private是针对compiler的, compiler负责语法检查。 运行时 是没有 public private限制的,只要代码到内存中,就可以调用执行。

5. 记事本程序实例

xmal代码:
  1. <Window x:Class="MyNoteBookProject.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">  
  5.         <DockPanel>  
  6.             <Menu DockPanel.Dock="Top" HorizontalAlignment="Left" VerticalAlignment="Top">  
  7.                 <MenuItem Header="File">  
  8.                     <MenuItem Header="New"></MenuItem>  
  9.                     <MenuItem Header="Open"></MenuItem>  
  10.                     <MenuItem Header="Add"></MenuItem>  
  11.                 </MenuItem>  
  12.                 <MenuItem Header="Edit">  
  13.                     <MenuItem Header="Cut"></MenuItem>  
  14.                     <MenuItem Header="Copy"></MenuItem>  
  15.                     <MenuItem Header="Paste"></MenuItem>  
  16.                </MenuItem>  
  17.                 <MenuItem Header="Extend" Name="PlugInMenuItem"></MenuItem>  
  18.             </Menu>  
  19.         <TextBox DockPanel.Dock="Bottom" Name="txt"></TextBox>  
  20.     </DockPanel>  
  21. </Window>  
<Window x:Class="MyNoteBookProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
        <DockPanel>
            <Menu DockPanel.Dock="Top" HorizontalAlignment="Left" VerticalAlignment="Top">
                <MenuItem Header="File">
                    <MenuItem Header="New"></MenuItem>
                    <MenuItem Header="Open"></MenuItem>
                    <MenuItem Header="Add"></MenuItem>
                </MenuItem>
                <MenuItem Header="Edit">
                    <MenuItem Header="Cut"></MenuItem>
                    <MenuItem Header="Copy"></MenuItem>
                    <MenuItem Header="Paste"></MenuItem>
               </MenuItem>
                <MenuItem Header="Extend" Name="PlugInMenuItem"></MenuItem>
            </Menu>
        <TextBox DockPanel.Dock="Bottom" Name="txt"></TextBox>
    </DockPanel>
</Window>

c#代码:
[csharp] view plain copy
print ?
  1. private void Window_Loaded(object sender, RoutedEventArgs e)  
  2. {  
  3.     AddPlugInsToMenu();  
  4. }  
  5.   
  6. //读取程序集文件,并生成 插件按钮  
  7. private void AddPlugInsToMenu() {  
  8.     // 获取正在运行的程序集 的 物理路径  
  9.     String assPath = this.GetType().Assembly.Location;  
  10.     // 获取 程序集 所有文件夹  
  11.     String assDirPath = System.IO.Path.GetDirectoryName(assPath);  
  12.     // 插件文件夹的路径  
  13.     String plugInDir = assDirPath + "\\plugs";  
  14.     // 扫描插件文件夹中的 所有 程序集文件名(获取所有dll文件)  
  15.     String[] dllFiles = System.IO.Directory.GetFiles(plugInDir, "*.dll");  
  16.     // 遍历程序集文件,并加载程序集文件到内存  
  17.     foreach(String strDll in dllFiles){  
  18.         // 根据程序集路径 加载程序集 到内存  
  19.         Assembly ass = Assembly.LoadFrom(strDll);  
  20.         // 判断程序集中是否有插件类  
  21.             // 获取程序集中的public类  
  22.         Type[] types = ass.GetExportedTypes();  
  23.         Type notebookInterfaceType = typeof(MyNoteBookPlugInterfaceProject.IPlugIn);  
  24.         // 判断是否实现了记事本接口  
  25.         foreach(Type t in types){  
  26.             // 判断t是否实现了 notebookInterfaceType 接口  
  27.             if (t.<span style="background-color: rgb(255, 255, 153);">IsAssignableFrom</span>(notebookInterfaceType)) {  
  28.                 // 根据插件类,创建menuitem,并添加到menu中  
  29.                 PlugInMenuItem.Items.Add(new MenuItem { Header = t.Name });  
  30.             }  
  31.         }  
  32.   
  33.          创建menuitem,并添加到menu中  
  34.         //PlugInMenuItem.Items.Add(new MenuItem { Header = strDll});  
  35.     }  
  36. }  
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            AddPlugInsToMenu();
        }

        //读取程序集文件,并生成 插件按钮
        private void AddPlugInsToMenu() {
            // 获取正在运行的程序集 的 物理路径
            String assPath = this.GetType().Assembly.Location;
            // 获取 程序集 所有文件夹
            String assDirPath = System.IO.Path.GetDirectoryName(assPath);
            // 插件文件夹的路径
            String plugInDir = assDirPath + "\\plugs";
            // 扫描插件文件夹中的 所有 程序集文件名(获取所有dll文件)
            String[] dllFiles = System.IO.Directory.GetFiles(plugInDir, "*.dll");
            // 遍历程序集文件,并加载程序集文件到内存
            foreach(String strDll in dllFiles){
                // 根据程序集路径 加载程序集 到内存
                Assembly ass = Assembly.LoadFrom(strDll);
                // 判断程序集中是否有插件类
                    // 获取程序集中的public类
                Type[] types = ass.GetExportedTypes();
                Type notebookInterfaceType = typeof(MyNoteBookPlugInterfaceProject.IPlugIn);
                // 判断是否实现了记事本接口
                foreach(Type t in types){
                    // 判断t是否实现了 notebookInterfaceType 接口
                    if (t.<span style="background-color: rgb(255, 255, 153);">IsAssignableFrom</span>(notebookInterfaceType)) {
                        // 根据插件类,创建menuitem,并添加到menu中
                        PlugInMenuItem.Items.Add(new MenuItem { Header = t.Name });
                    }
                }

                 创建menuitem,并添加到menu中
                //PlugInMenuItem.Items.Add(new MenuItem { Header = strDll});
            }
        }
另一个记事本公司开发的dll中, 有一个接口, 在wpf程序中add ref这个程序集。其他开发plugin的公司,也必须add ref这个程序集。
[csharp] view plain copy
print ?
  1. namespace MyNoteBookPlugInterfaceProject  
  2. {  
  3.     public interface IPlugIn  
  4.     {  
  5.         String ProcessText(String text);  
  6.     }  
  7. }  
namespace MyNoteBookPlugInterfaceProject
{
    public interface IPlugIn
    {
        String ProcessText(String text);
    }
}

开发plugin的公司:写一个class library project, 也add ref记事本公司开发的接口程序集。写实现了这个接口的插件类。build这个程序集,把dll放到记事本项目的plugInDir目录下。这个plugin就可以使用了。
[csharp] view plain copy
print ?
  1. namespace NoteBookPlugIn  
  2. {  
  3.     public class PlugToUpper : MyNoteBookPlugInterfaceProject.IPlugIn  
  4.     {  
  5.   
  6.         public string ProcessText(string text)  
  7.         {  
  8.             return text.ToUpper();  
  9.         }  
  10.     }  
  11. }</strong>  
namespace NoteBookPlugIn
{
    public class PlugToUpper : MyNoteBookPlugInterfaceProject.IPlugIn
    {

        public string ProcessText(string text)
        {
            return text.ToUpper();
        }
    }
}</strong>
[csharp] view plain copy
print ?
  1. <strong>namespace NoteBookPlugIn  
  2. {  
  3.     public class PlugToLower : IPlugIn  
  4.     {  
  5.         public string ProcessText(string text)  
  6.         {  
  7.             return text.ToLower();  
  8.         }  
  9.     }  
  10. }  
<strong>namespace NoteBookPlugIn
{
    public class PlugToLower : IPlugIn
    {
        public string ProcessText(string text)
        {
            return text.ToLower();
        }
    }
}

运行结果:

6. 动态创建对象

1. 通过Activator创建
object o = Activator.CreateInstance(Type type);
会调用无参数的构造函创建一个对象,如果没有无参数的构造函数,异常。
2. 通过 构造器 创建(Type类示例4


  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
两个现实中的例子: 1、B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况。这是如何做到的呢?B超是B型超声波,它可以透过肚皮通过向你体内发射B型超声波,当超声波遇到内脏壁的时候就会产生一定的“回音”反射,然后把“回音”进行处理就可以显示出内脏的情况了(我不是医生也不是声学专家,不知说得是否准确^_^)。 2、地球内部结构:地球的内部结构大体可以分为三层:地壳、地幔和地核。地壳是固体,地核是液体,地幔则是半液半固的结构(中学地理的内容,大家还记得吧?)。如何在地球表面不用深入地球内部就知道其内部的构造呢?对,向地球发射“地震波”,“地震波”分两种一种是“横波”,另一种是“纵波”。“横波”只能穿透固体,而“纵波”既可穿透固体又可以穿透液体。通过在地面对纵波和横波的反回情况,我们就可以大体断定地球内部的构造了。 大家注意到这两个例子的共同特点,就是从一个对象的外部去了解对象内部的构造,而且都是利用了波的反射功能。在.NET中的反射也可以实现从对象的外部来了解对象(或程序集)内部结构的功能,哪怕你不知道这个对象(或程序集)是个什么东西,另外.NET中的反射还可以运态创建出对象并执行它其中的方法。 反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。 反射的用途: (1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。 (2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 (3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。 (4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。 (5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。 (6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。 (7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。 (8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。 反射用到的命名空间: System.Reflection System.Type System.Reflection.Assembly 反射用到的主要类: System.Type 类--通过这个类可以访问任何给定数据类型的信息。 System.Reflection.Assembly类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。 System.Type类: System.Type 类对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。 获取给定类型的Type引用有3种常用方式: ●使用 C# typeof 运算符。 Type t = typeof(string); ●使用对象GetType()方法。 string s = "grayworm"; Type t = s.GetType(); ●还可以调用Type类的静态方法GetType()。 Type t = Type.GetType("System.String"); 上面这三类代码都是获取string类型的Type,在取出string类型的Type引用t后,我们就可以通过t来探测string类型的结构了。 string n = "grayworm"; Type t = n.GetType(); foreach (MemberInfo mi in t.GetMembers()) { Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name); } Type类的属性: Name 数据类型名 FullName 数据类型的完全限定名(包括命名空间名) Namespace 定义数据类型的命名空间名 IsAbstract 指示该类型是否是抽象类型 IsArray 指示该类型是否是数组 IsClass 指示该类型是否是类 IsEnum 指示该类型是否是枚举 IsInterface 指示该类型是否是接口 IsPublic 指示该类型是否是公有的 IsSealed 指示该类型是否是密封类 IsValueType 指示该类型是否是值类型 Type类的方法: GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息 GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息 GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息 GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息 GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息 GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息 GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息 可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。 查看类中的构造方法: NewClassw nc = new NewClassw(); Type t = nc.GetType(); ConstructorInfo[] ci = t.GetConstructors(); //获取类的所有构造函数 foreach (ConstructorInfo c in ci) //遍历每一个构造函数 { ParameterInfo[] ps = c.GetParameters(); //取出每个构造函数的所有参数 foreach (ParameterInfo pi in ps) //遍历并打印所该构造函数的所有参数 { Console.Write(pi.ParameterType.ToString()+" "+pi.Name+","); } Console.WriteLine(); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值