反射和codedom

来源:互联网 发布:hadoop入门书籍 知乎 编辑:程序博客网 时间:2024/04/30 03:51

Type t = listBox1.GetType();                       

object o = t.GetProperty("Items").GetValue(listBox1,null);

 

MethodInfo mi = o.GetType().GetMethod("Clear");

mi.Invoke(o,null);        

 

<---------------------------------------------------------------------->

Type t = FindType("System.Windows.Forms.TextBox");

 

ConstructorInfo ci = t.GetConstructor(new Type[]{});

object o = ci.Invoke(null);

 

this.Controls.Add((Control)o);

<---------------------------------------------------------------------->

Type t = listBox1.GetType();

object o = t.GetProperty("Items").GetValue(listBox1,null);

 

o.GetType().InvokeMember("Clear",BindingFlags.InvokeMethod,null,o,null);

此技术是.NET Framework中用来产生程序代码的基础建设,它以对象化的方式仿真出程序代码的逻辑,最后交由特定的Code Provider对象来产生出源程序代码。由于CodeDOM是高度对象化后的程序逻辑对象,因此由此技术所产生的程序代码会随着使用Code Provider对象类型而改变,也就是说当设计人员将CodeDOM对象交给CSharpCodeProvider对象产生程序代码时,其产生的将是C#的源代码,Code ProviderVBCodeProvider时,其产生的就是VB.NET的程序代码。CodeDOM技术应用于许多地方,例如IDE Code SerializerASP.NET Just-In-Time Compiler等中都有其身影存在。不过CodeDOM拥有庞大的对象群,常让设计人员有种不知由何着手的感觉,但是一旦了解了其中几个对象后,你就会发现这些对象的用法是相当直观的。

2-4-1  CodeCompileUnitCodeNamespace

    CodeCompileUnitCodeDOM中的根容器型对象,其内可以加入CodeNamespace对象来产namespace语句,程序2-23的程序代码片段示范了此用法。

程序2-23  运用CodeCompileUnit对象的范例

using System.IO;

using System.CodeDom;

using System.CodeDom.Compiler;

using Microsoft.CSharp;

 

..............

 

CodeCompileUnit unit = new CodeCompileUnit();

 

CodeDomProvider provider = new CSharpCodeProvider();

StringWriter sw = new StringWriter();

ICodeGenerator generator = provider.CreateGenerator();

 

unit.Namespaces.Add(new CodeNamespace("MyNamespace"));

 

generator.GenerateCodeFromCompileUnit(unit,sw,

                                              new CodeGeneratorOptions());

    程序2-23会产生程序2-24C#源代码。

程序2-24  由程序2-23所产生的C#源代码

namespace MyNamespace {   

}

2-4-2  CodeNamespaceImportCodeTypeDeclaration

    CodeNamespaceImport对象用来产生using xxx类引Namespace的程序代码,目前CodeDOM的实现只允许用户经由CodeNamespace对象来加入CodeNamespaceImport象。CodeTypeDeclaration则是用来产生声明类型的对象,它可以处理类、枚举、结构、接口,与CodeNamespaceImport对象相同,此对象也只允许经由CodeNamespace对象来加入,程序2-25的程序代码片段示范这两个对象的用法。

程序2-25  运用CodeNamespaceImportCodeTypeDeclaration对象的范例

CodeNamespace cNS = new CodeNamespace("MyNamespace");

cNS.Imports.Add(new CodeNamespaceImport("System"));

CodeTypeDeclaration cClass = new CodeTypeDeclaration("MyClass");

CodeTypeDeclaration cInterface= 
  new CodeTypeDeclaration("IMyInterface") ;

cInterface.IsInterface = true;

cNS.Types.Add(cClass);

cNS.Types.Add(cInterface);

unit.Namespaces.Add(cNS);

<----------------------------------------------------------->

//2-25所产生的源代码

namespace MyNamespace {

    using System;   

    public class MyClass {

    }

   

    public interface IMyInterface {

    }

}

 

    CodeTypeDeclaration对象允许用户指定产生类型的修饰符,2-26的程序代码片段示范如何产生一个抽象类。

程序2-26  运用CodeTypeDeclaration产生一个抽象类的范例

using refl = System.Reflection;

......

CodeTypeDeclaration cClass = new CodeTypeDeclaration("MyClass");

cClass.TypeAttributes = refl.TypeAttributes.Abstract | 
                             refl.TypeAttributes.Public;

 

    读者可于On-Line Help查到System.Reflection.TypeAttributes其他的可能值。另外CodeTypeDeclaration对象也允许指定基础类,设计者可经由BaseType性来加入基础类,如程序2-27所示。

程序2-27  CodeTypeDeclaration定基础类

cClass.BaseTypes.Add(new CodeTypeReference(typeof(
                                             System.Windows.Forms.Control)));

2-4-3  CodeMemberFieldCodeMemberMethod
       CodeMemberProperty
CodeMemberEvent

    这四个对象分别可以产生成员函数、成员变量、成员事件、成员属性四种声明型程序代码,它们必须经由CodeTypeDeclaration.Members对象来加入,见程序2-28

程序2-28  使用CodeMemberField等四种对象的范例

CodeTypeDeclaration cClass = new CodeTypeDeclaration("MyClass");

CodeMemberField cField = new CodeMemberField(typeof(int),"m_int");

CodeMemberMethod cMethod = new CodeMemberMethod();

cMethod.Name = "TestMethod";

CodeMemberProperty cProperty = new CodeMemberProperty();

cProperty.Name = "TestProperty";

cProperty.HasGet = true;

cProperty.Type = new CodeTypeReference(typeof(int));

cProperty.GetStatements.Add(new CodeMethodReturnStatement(

                              new CodeFieldReferenceExpression(

                              new CodeBaseReferenceExpression(),"m_int")));

cClass.Members.Add(cField);

cClass.Members.Add(cProperty);

cClass.Members.Add(cMethod);

 

    先由CodeMemberMethod对象谈起,一个成员函数可以拥有参数及返回值,范例程序中并未预定义TestMethod函数的返回值及参数信息,这会产生一个无返回值与参数的函数,如用户须预定义这些信息时,必须经由其ReturnTypeParameter属性来设定,如程序2-29所示。

程序2-29  CodeMemberMethod指定ReturnTypeParameter

cMethod.ReturnType = new CodeTypeReference(typeof(int));

cMethod.Parameters.Add(

   new CodeParameterDeclarationExpression(typeof(int),"int1"));

cMethod.Statements.Add(new CodeMethodReturnStatement(
                            new CodePrimitiveExpression(0)));

 

    前两行用来预定义函数的返回值及参数,第三行是预定义函数内的程序代码,此处使用CodeMethodReturnStatement对象来预定义一个return语句,CodePrimitiveExpression对象则预定义一个内建类型的值,此处是数值0CodeMemberProperty是预定义成员属性的对象,它有几个重要的设定,HasGetHasSet代表这个属性是否拥有getset区段,当设定了其中一个为True之后,连带必须在GetStatement或是SetStatement属性加入语句,范例中在GetStatement属性内加入了一个CodeMethodReturnStatement对象,并于其中加入了一个CodeFieldReferenceExpression对象,这是用来预定义成员变量引用的语句,于其内又预定义了CodeBaseReferenceExpression对象,这会产生引用至base的语句,整个范例产生的结果见程序2-30

程序2-30  程序2-29所产生的程序代码

namespace MyNamespace {

    using System;   

    public class MyClass {       

        private int m_int;       

        private int TestProperty {

            get {

                return base.m_int;

            }

        }       

        private int TestMethod(int int1) {

            return 0;

        }

    }

}

原创粉丝点击