反射和codedom

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;

        }

    }

}

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
using CodeEditor.CodeEdit; using Microsoft.CSharp; using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CodeEditor { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void btnCompile_Click(object sender, EventArgs e) { //【1】新建C#代码生成器和代码编译器的实例 CodeDomProvider Provider = CodeDomProvider.CreateProvider("CSharp"); //【2】配置用于调用编译器的参数 CompilerParameters Parameters = new CompilerParameters(); Parameters.ReferencedAssemblies.Add("System.dll"); Parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll"); Parameters.ReferencedAssemblies.Add("System.Linq.dll"); Parameters.GenerateExecutable = false; Parameters.GenerateInMemory = true; //【3】启动编译 CompilerResults Result = Provider.CompileAssemblyFromSource(Parameters, rtbCode.Text); if (Result.Errors.HasErrors) { AppendInfo("编译错误:"); foreach (CompilerError err in Result.Errors) { AppendInfo(err.ErrorText); } } else { // 通过反射,调用实例 Assembly objAssembly = Result.CompiledAssembly; object objHelloWorld = objAssembly.CreateInstance("CodeEditor.CodeEdit.Code"); MethodInfo objMI = objHelloWorld.GetType().GetMethod("Test"); object ReValue = objMI.Invoke(objHelloWorld, null); AppendInfo(ReValue); } } //追加字符 private void AppendInfo(object Info) { rtbResult.Text =Info+"\n\r"; } } }
最新发布
07-17
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值