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


猜你喜欢

转载自blog.csdn.net/cjb_king/article/details/80521481