微软CodeDom模型学习笔记(全)

要点1

CodeDomProvider

MSDN描述

CodeDomProvider可用于创建和检索代码生成器和代码编译器的实例。代码生成器可用于以特定的语言生成代码,而代码编译器可用于将代码编译为程序集。

      注意: .NET Framework 2.0版中,在代码生成器和代码编译器中可用的方法可直接从代码提供程序获得。您不需要调用CreateGenerator CreateCompiler 来访问这些方法,这些方法被标记为已过时。这适用于预先存在的以及新的代码提供程序实现。

CodeDomProvider类提供静态方法以发现和枚举计算机上的CodeDomProvider实现。GetAllCompilerInfo方法返回计算机上所有CodeDomProvider实现的设置。GetCompilerInfo方法会基于编程语言名称返回特定CodeDomProvider实现的设置。CreateProvider方法返回特定语言的CodeDomProvider实现的实例。

CodeDomProvider可用于创建和检索代码生成器和代码编译器的实例。代码生成器可用于以特定的语言生成代码,而代码编译器可用于将代码编译为程序集。

.NET Framework 1.0版和 1.1版中,代码提供程序包含CodeDomProviderICodeGeneratorICodeParserICodeCompiler的实现。

.NET Framework 2.0中,CreateGeneratorCreateParserCreateCompiler方法已过时ICodeGeneratorICodeCompiler 的方法在CodeDomProvider 类中直接可用

1,GetAllCompilerInfo方法,返回类型:CompilerInfo[]

根据返回的CompilerCodeDomProviderType(本身为Type类型)可以得到如下信息

编译类型名称:CSharpCodeProvider,全名Microsoft.CSharp.CSharpCodeProvider

编译类型名称:VBCodeProvider,全名Microsoft.VisualBasic.VBCodeProvider

编译类型名称:JScriptCodeProvider,全名Microsoft.JScript.JScriptCodeProvider

编译类型名称:VJSharpCodeProvider,全名Microsoft.VJSharp.VJSharpCodeProvider

编译类型名称:CppCodeProvider,全名Microsoft.VisualC.CppCodeProvider

CompilerInfIsCodeDomProviderTypeValid为另一重要属性,用处描述为

返回一个值,该值指示是否在计算机上配置了语言提供程序实现。

备注:生成CodeDomProvider实例方式1CompilerinfCreateProvider

CompilerInfGetLanguages方法返回一个string[],其中的每个string可以用来调用CodeDomProvider.CreateProvider(string name)来生成一个CodeDomProvider实例,这是另一种生成CodeDomProvider实例的方式

下面是在本机支持的所有语言,可以用作CodeDomProvider.CreateProvider(string name)参数。

c# , cs , csharp

vb , vbs , visualbasic

vbscript,js , jscript , javascript

vj# , vjs , vjsharp

c++ , mc , cpp

CompilerInfGetExtensions,返回受语言提供程序支持的文件扩展名。

本段学习的代码段

 

1,GenerateCodeFromExpression方法

 MSDN描述:为指定的代码文档对象模型 (CodeDOM) 表达式生成代码,并使用指定的选项将代码发送到指定的文本编写器。

通俗理解:CodeEcpression输出为代码字符串

 代码准备工作:

           1,CodeGeneratorOptions options=newCodeGeneratorOptions ();

           2,options .BlankLinesBetweenMembers =true;

           3,options .BracingStyle ="C";

           4,options .ElseOnClosing =false ;

           5,options .IndentString=" ";

           6,options["CustomGeneratorOptionStringExampleID"] ="BuildFlags: /A /B /C /D /E";

           7,StringBuilder sb =new StringBuilder(200);            

           8,using (TextWriter tw =new StringWriter(sb))

1:为GenerateCodeFromExpression生成的代码提供一些选项

2:获取或设置一个值,该值指示是否在成员之间插入空行。

3:获取或设置用于大括号的样式。

4:获取或设置一个值,该值指示是否在前面每个iftry块的结束行处追加elsecatchfinally块(包括括号)。

5:获取或设置用于缩进的字符串。

6:获取或设置指定索引处的对象。(不理解,msdn上有备注如下

此字典为开发人员提供了一个扩展性机制,可为代码生成器的自定义功能提供数据。代码生成器必须实现这样的功能并支持检查字典,这种机制才会有用。

78:准备好GenerateCodeFromExpression的输出流.

说明:本文里出现的"输出的代码字符串为:"就是指sb.ToString()的值

测试各种CodeExpression(表达式)

 可以用这些表达式模型一一地对应生成的对应语言的代码

a, CodeBinaryOperatorExpression,表示一个表达式,该表达式包含在两个表达式间进行的二进制运算。

通俗理解为基本的加减乘除之类的表达式。

CodeExpression left =newCodePrimitiveExpression(1);

CodeExpression right=newCodePrimitiveExpression(2);

CodeBinaryOperatorExpression addMethod =new CodeBinaryOperatorExpression(left,CodeBinaryOperatorType.Add,right);

codeProvider.GenerateCodeFromExpression(addMethod, tw, options);

输出的代码字符串为:(1 + 2)

   

CodeBinaryOperatorExpression left =new CodeBinaryOperatorExpression();

left.Left =new CodePrimitiveExpression(3);

left.Operator =CodeBinaryOperatorType.Multiply;

left.Right =new CodePrimitiveExpression(4); 

CodeExpression right=newCodePrimitiveExpression(2);

CodeBinaryOperatorExpression addMethod =new CodeBinaryOperatorExpression(left,CodeBinaryOperatorType.Add,right);

codeProvider.GenerateCodeFromExpression(addMethod, tw, options);

输出的代码字符串为:((3 * 4) + 2)

备注:CodePrimitiveExpression可用于表示一个表达式,该表达式指示基元数据类型的值.

如果类型不对,在生成代码的时候会提示

  

b, CodeArgumentReferenceExpression,表示对传递到方法的参数值的引用。

这个表达式相对简单,一笔带过

CodeArgumentReferenceExpression arg =new CodeArgumentReferenceExpression("param1");

codeProvider.GenerateCodeFromExpression(arg, tw, options);

输出的代码字符串为:param1

c, CodeArrayCreateExpression表示创建数组的表达式。

简单地解释:如要int[] arr=new int[10]CodeArrayCreateExpression可以代表等号后面的红色部分。

CodeArrayCreateExpression arr =new CodeArrayCreateExpression("System.Int32", 10);

codeProvider.GenerateCodeFromExpression(arr, tw, options);

输出的代码字符串为:new int[10]

d,CodeArrayIndexerExpression表示对数组的索引的引用下面的代码表示应用数组X的第二个元素,X[2]

CodeVariableReferenceExpression arrName =new CodeVariableReferenceExpression("x");

CodeArrayIndexerExpression idx =new CodeArrayIndexerExpression(arrName,new CodePrimitiveExpression(2));

StringBuilder sb =new StringBuilder(200);  

codeProvider.GenerateCodeFromExpression(idx , tw, options);

输出的代码字符串为:x[2]

e,CodeBaseReferenceExpression表示对基类的引用。

base.Dispose()为例,生成前面的base

CodeBaseReferenceExpression ret =new CodeBaseReferenceExpression();

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:base

f, CodeCastExpression表示到一种数据类型或接口的表达式转换。

比如将100转换为双精度类型:

CodeCastExpression ret =new CodeCastExpression();

ret.TargetType =new CodeTypeReference("System.Double");

ret.Expression =new CodePrimitiveExpression(100); 

codeProvider.GenerateCodeFromExpression(ret , tw, options);

输出的代码字符串为:((double)(100))

g, CodeDefaultValueExpression表示对默认值的引用。

比如int的默认值表示为:default(int)

CodeDefaultValueExpression ret =new CodeDefaultValueExpression();

ret.Type =new CodeTypeReference("String");

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:default(String)

h, CodeDelegateCreateExpression表示创建委托的表达式。

CodeDelegateCreateExpression ret =new CodeDelegateCreateExpression();

ret.DelegateType =new CodeTypeReference(typeof(System.EventHandler));

ret.MethodName ="TestMethod";

ret.TargetObject =new CodeThisReferenceExpression();

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:new System.EventHandler(this.TestMethod)

i, CodeDelegateInvokeExpression表示引发事件的表达式。

CodeDelegateInvokeExpression ret =new CodeDelegateInvokeExpression();

ret.TargetObject =new CodeEventReferenceExpression(newCodeThisReferenceExpression(), "TestEvent");//对应this.TestEvent

ret.Parameters.Add(newCodeThisReferenceExpression());//对应this参数

ret.Parameters .Add (newCodeObjectCreateExpression(typeof(EventArgs )));//对应new System.EventArgs()参数

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.TestEvent(this, new System.EventArgs())

j,CodeDirectionExpression表示用作方法调用参数及引用方向指示器的表达式。In,out,ref3种类型

CodeDirectionExpression ret =new CodeDirectionExpression();

ret.Direction =FieldDirection.Ref;

ret.Expression =new CodeFieldReferenceExpression(null,"TestParameter");

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:ref TestParameter

K, CodeEventReferenceExpression表示对事件的引用。

CodeEventReferenceExpression ret =new CodeEventReferenceExpression();

ret.TargetObject =new CodeThisReferenceExpression();

ret.EventName ="Click";

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.Click

l, CodeFieldReferenceExpression表示对某字段的引用.

CodeFieldReferenceExpression ret =new CodeFieldReferenceExpression();

ret.TargetObject =new CodeThisReferenceExpression();

ret.FieldName ="m_field1";

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.m_field1

m, CodeIndexerExpression表示对对象的索引器属性的引用。

CodeIndexerExpression ret =new CodeIndexerExpression();

ret.TargetObject =new CodeThisReferenceExpression();

ret.Indices.Add(newCodePrimitiveExpression(1));

ret.Indices.Add(newCodePrimitiveExpression(1));

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this[1, 1]

n, CodeMethodInvokeExpression表示调用方法的表达式。

CodeMethodInvokeExpression ret =new CodeMethodInvokeExpression();

ret.Method =new CodeMethodReferenceExpression();

ret.Method.TargetObject =new CodeThisReferenceExpression();

ret.Method.MethodName ="Dispose";

ret.Parameters.Add(newCodePrimitiveExpression(true)); 

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.Dispose(true)

o, CodeMethodReferenceExpression表示方法的引用。

CodeMethodReferenceExpression ret =new CodeMethodReferenceExpression();

ret.TargetObject =new CodeThisReferenceExpression();

ret.MethodName ="Dispose";

ret.TypeArguments.Add(new CodeTypeReference(typeof(Boolean)));

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.Dispose<bool>

如果注释掉绿色的行,则

输出的代码字符串为:this.Dispose

p,CodeObjectCreateExpression表示创建某种类型的新实例的表达式。

CodeObjectCreateExpression ret =new CodeObjectCreateExpression();

ret.CreateType =new CodeTypeReference(typeof(Int32));

ret.Parameters.Add(newCodePrimitiveExpression(11));

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:new int(11)

q, CodeParameterDeclarationExpression表示方法、属性或构造函数的参数声明。

CodeParameterDeclarationExpression ret =new CodeParameterDeclarationExpression();

ret.Direction =FieldDirection.Ref;

ret.Name ="arg1";

ret.Type =new CodeTypeReference(typeof(String));

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:ref string arg1

r, CodePrimitiveExpression前面已经介绍。

s,CodePropertyReferenceExpression表示属性值的引用。

CodePropertyReferenceExpression ret =new CodePropertyReferenceExpression();

ret.TargetObject =new CodeThisReferenceExpression();

ret.PropertyName ="Property1";

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this.Property1

t, CodePropertySetValueReferenceExpression表示属性集方法内的属性集方法调用的值参数。

C#来说,就是指value

CodePropertySetValueReferenceExpression ret =new CodePropertySetValueReferenceExpression();

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:value

u, CodeSnippetExpression表示文本表达式。

文本表达式将表达式的代码存储为原义代码片段。CodeDOM不翻译原义代码片段。原义代码片段是完全按照原样存储和输出的。提供包含原义代码的 CodeDOM对象,以便开发人员可以封装已经成为目标语言的代码。

CodeSnippetExpression ret =new CodeSnippetExpression();

ret.Value ="任意代码段";

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:任意代码段

v, CodeThisReferenceExpression表示对当前本地类实例的引用。

它可以表示"this""me"所引用的类对象。

CodeThisReferenceExpression ret =new CodeThisReferenceExpression();

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:this

w, CodeTypeOfExpression表示typeof表达式,该表达式返回指定类型名称的 Type

CodeTypeOfExpression ret = new CodeTypeOfExpression();

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

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:typeof(int)

x, CodeTypeReferenceExpression表示对某数据类型的引用。

CodeTypeReferenceExpression ret =new CodeTypeReferenceExpression();

ret.Type =new CodeTypeReference(typeof(DateTime));

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:System.DateTime

z, CodeVariableReferenceExpression表示局部变量的引用。

CodeVariableReferenceExpression ret =new CodeVariableReferenceExpression();

ret.VariableName ="_localVar";

codeProvider.GenerateCodeFromExpression(ret, tw, options);

输出的代码字符串为:_localVar

  

2,codeProvider.GenerateCodeFromStatement方法

为指定的代码文档对象模型 (CodeDOM)语句生成代码,并使用指定的选项将代码发送到指定的文本编写器。

通俗理解:CodeAssignStatement输出为代码字符串

测试各种CodeStatement(语句)

可以用这些语句模型一一地对应生成的对应语言的代码

a, CodeAssignStatement表示简单的赋值语句。

CodeAssignStatement ret =new CodeAssignStatement();

CodeVariableReferenceExpression left =new CodeVariableReferenceExpression();

left.VariableName ="i";

ret.Left = left;

ret.Right =new CodePrimitiveExpression(33);

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:i = 33;

把右边换成变量的应用CodeVariableReferenceExpression

CodeAssignStatement ret =new CodeAssignStatement();

CodeVariableReferenceExpression left =new CodeVariableReferenceExpression();

left.VariableName ="i";

ret.Left = left;

CodeVariableReferenceExpression right =new CodeVariableReferenceExpression();

right.VariableName ="j";

ret.Right = right;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:i = j;

把右边换成函数调用的返回结果CodeMethodInvokeExpression

CodeAssignStatement ret =new CodeAssignStatement();

CodeVariableReferenceExpression left =new CodeVariableReferenceExpression();

left.VariableName ="i";

ret.Left = left;

CodeMethodInvokeExpression right =new CodeMethodInvokeExpression();

right.Method =new CodeMethodReferenceExpression();

right.Method.TargetObject =new CodeVariableReferenceExpression("myField");

right.Method.MethodName ="TestMethod";

right.Parameters.Add(newCodePrimitiveExpression(true));

ret.Right = right;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:i = myField.TestMethod(true);

b,表示向事件附加事件处理程序委托的语句。

CodeAttachEventStatement ret =new CodeAttachEventStatement();

CodeEventReferenceExpression myEvent =new CodeEventReferenceExpression();

myEvent.TargetObject =new CodeThisReferenceExpression();

myEvent.EventName ="Click";

ret.Event = myEvent;

CodeDelegateCreateExpression myDelegate =new CodeDelegateCreateExpression();

myDelegate.TargetObject =new CodeThisReferenceExpression();

myDelegate.MethodName ="On_Click";

myDelegate.DelegateType =new CodeTypeReference(typeof(EventHandler<EventArgs>));

ret.Listener = myDelegate;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:this.Click += new System.EventHandler<System.EventArgs>(this.On_Click);

c, CodeCommentStatement表示由单个注释构成的语句。

CodeCommentStatement ret =new CodeCommentStatement();

ret.Comment =new CodeComment("这是一些单行注释!",false);

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为://这是一些单行注释!

第二个参数设置为true时,输出3个"/"

CodeCommentStatement ret =new CodeCommentStatement();

ret.Comment =new CodeComment("这是一些单行注释!",true);

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:///这是一些单行注释!

d, CodeConditionStatement表示条件分支语句,通常表示为一个if语句。

CodeConditionStatement可用于表示由一个条件表达式、一个在条件表达式计算为true时执行的语句集合和一个在条件表达式计算为false时执行的可选语句集合组成的代码。在许多语言中,CodeConditionStatement都生成为if语句。

Condition属性指示要测试的表达式。TrueStatements属性包含当要测试的表达式计算为true时要执行的语句。FalseStatements属性包含当要测试的表达式计算为false时要执行的语句。

CodeConditionStatement ret =new CodeConditionStatement();

ret.Condition =new CodeVariableReferenceExpression("flag");

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:

if (flag)

{

}

加上else条件

CodeConditionStatement ret =new CodeConditionStatement();

ret.Condition =new CodeVariableReferenceExpression("flag");

ret.FalseStatements.Add(newCodeCommentStatement("dddddddddddddd")); 

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:

if (flag)

{

} else

{

 // dddddddddddddd

}

**如何加上else if形式,还在研究中

  

c, CodeExpressionStatement表示由单个表达式组成的语句。

由一个new表达式构成的单个语句

CodeExpressionStatement ret =new CodeExpressionStatement();

CodeDelegateCreateExpression createDelegate =new CodeDelegateCreateExpression();

createDelegate.DelegateType =new CodeTypeReference(typeof(EventHandler<EventArgs>));

createDelegate.MethodName ="OnClick";

createDelegate.TargetObject =new CodeThisReferenceExpression();

ret.Expression = createDelegate;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:new System.EventHandler<System.EventArgs>(this.OnClick);

由一个函数调用表达式构成的单个语句

CodeExpressionStatement ret =new CodeExpressionStatement();

CodeMethodInvokeExpression methodInvoke =new CodeMethodInvokeExpression();

methodInvoke.Method.MethodName ="MyMethod";

methodInvoke.Method.TargetObject =new CodeThisReferenceExpression();

methodInvoke.Method.TypeArguments.Add(newCodeTypeReference(typeof(string)));

methodInvoke.Parameters.Add(newCodeVariableReferenceExpression("arg"));

ret.Expression = methodInvoke;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:this.MyMethod<string>(arg);

d, CodeGotoStatement表示goto语句。

并非所有语言都支持goto 语句。使用GotoStatements标志调用Supports方法可确定代码生成器是否支持goto 语句。

CodeGotoStatement ret =new CodeGotoStatement();

ret.Label ="gotoLabel";

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:goto gotoLabel;

e,CodeIterationStatement表示for语句或语句块内的循环(使用测试表达式作为继续循环的条件)。

InitStatement属性指定在第一次循环迭代之前执行的语句。TestExpression属性指定循环继续表达式,该表达式在每次循环迭代结束时的计算结果必须为true才能开始下一次迭代。IncrementStatement属性指定每次循环迭代结束时执行的语句。Statements属性指定循环内执行的语句集合。

CodeIterationStatement ret =new CodeIterationStatement();

ret.IncrementStatement =new CodeSnippetStatement("++i");

ret.InitStatement =new CodeSnippetStatement("int i=0");

ret.TestExpression =new CodeSnippetExpression("i<100"); 

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:;

for (int i=0

; i<100; ++i

)

{

}

可以为循环体加任意的语句

CodeIterationStatement ret =new CodeIterationStatement();

ret.IncrementStatement =new CodeSnippetStatement("++i");

ret.InitStatement =new CodeSnippetStatement("int i=0");

ret.TestExpression =new CodeSnippetExpression("i<100"); 

ret.Statements.Add(newCodeCommentStatement("这里可以添加循环体里面的代码语句!")); 

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:;

for (int i=0

; i<100; ++i

)

{

 //这里可以添加循环体里面的代码语句!

}

f, CodeLabeledStatement表示标记语句或独立标签。

并非所有的语言都支持goto 语句和标签,所以,您应该测试代码生成器是否支持goto 语句和标签;方法是:调用带有GotoStatements标志的Supports方法。

CodeLabeledStatement ret =new CodeLabeledStatement();

ret.Label ="myLabel";

ret.Statement =new CodeSnippetStatement("return;");

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:

myLabel:

return;

与goto语句配合起来使用

CodeConditionStatement ret =new CodeConditionStatement();

ret.Condition =new CodeVariableReferenceExpression("flag");

CodeGotoStatement gotoStatement =new CodeGotoStatement();

gotoStatement.Label ="myLabel";

ret.TrueStatements.Add(newCodeSnippetStatement("//做点有意义的事情!"));

ret.TrueStatements.Add(gotoStatement); 

CodeLabeledStatement label =new CodeLabeledStatement();

label.Label ="myLabel";

label.Statement =new CodeSnippetStatement("//做点清理工作!");

ret.FalseStatements.Add(label); 

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:

if (flag)

{

//做点有意义的事情!

 goto myLabel;

} else

{

myLabel:

//做点清理工作!

}

g, CodeMethodReturnStatement表示返回值语句。

CodeMethodReturnStatement ret =new CodeMethodReturnStatement();

ret.Expression =new CodeSnippetExpression("this.ToString()"); 

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:return this.ToString();

h, CodeRemoveEventStatement表示移除事件处理程序的语句。

CodeRemoveEventStatement ret =new CodeRemoveEventStatement();

ret.Event =new CodeEventReferenceExpression();

ret.Event.TargetObject =new CodeThisReferenceExpression();

ret.Event.EventName ="Click";

CodeDelegateCreateExpression myDelegate=new CodeDelegateCreateExpression();

myDelegate.TargetObject =new CodeVariableReferenceExpression("myMember");

myDelegate.MethodName ="OnClick";

myDelegate.DelegateType =new CodeTypeReference(typeof(EventHandler<EventArgs>));

ret.Listener = myDelegate;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:this.Click -= new System.EventHandler<System.EventArgs>(myMember.OnClick);

i, CodeSnippetStatement使用原义代码片断表示一条语句。

CodeSnippetStatement可使用原义代码片断表示一条语句,该原义代码片断无需修改就可直接包括在源代码中。

CodeSnippetStatement将代码节完全按照其原始格式存储为字符串。CodeDOM不翻译原义代码片段。原义代码片段按其原始格式存储和输出。提供包含原义代码的 CodeDOM对象,以便开发人员可以封装已经成为目标语言的代码。

Value属性包含该小块语句的原义代码。

前面已经用了很多了,不再单独记录了。

j, CodeThrowExceptionStatement表示引发异常的语句。

CodeThrowExceptionStatement可表示引发异常的语句。该表达式应为或计算为从 Exception类派生的类型的实例的引用。ToThrow属性指定要引发的异常。

CodeThrowExceptionStatement ret =new CodeThrowExceptionStatement();

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:throw;

为ToThrow设置具体的异常

CodeThrowExceptionStatement ret =new CodeThrowExceptionStatement();

CodeObjectCreateExpression exp= new CodeObjectCreateExpression();

exp.CreateType =new CodeTypeReference(typeof(Exception));

ret.ToThrow = exp;

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:throw new System.Exception();

k, CodeTryCatchFinallyStatement 表示一个try块,具有任意数量的catch子句和一个可选的finally块。

TryStatements属性包含try 块内要执行的语句。CatchClauses属性包含要处理已捕获异常的catch 子句。FinallyStatements属性包含finally 块内要执行的语句。

并非所有的语言都支持try/catch 块。使用GeneratorSupport..::.TryCatchStatements标志调用Supports 方法以确定代码生成器是否支持try/catch 块。

CodeTryCatchFinallyStatement ret = new CodeTryCatchFinallyStatement();

ret.TryStatements.Add(newCodeSnippetExpression("throw new Exception();"));

CodeCatchClause catch1=newCodeCatchClause ();

catch1 .CatchExceptionType =newCodeTypeReference (typeof (System .Data .DataException));

catch1 .LocalName="dataException";

catch1 .Statements.Add(newCodeSnippetStatement("MessageBox.Show(/"数据库错误!/");"));

ret.CatchClauses.Add(catch1);

   

CodeCatchClause catch2 =new CodeCatchClause();

catch2.CatchExceptionType =new CodeTypeReference(typeof(Exception));

catch2.LocalName ="ex";

catch2.Statements.Add(newCodeSnippetStatement("MessageBox.Show(/"未知的错误!/");"));

ret.CatchClauses.Add(catch2);

   

ret.FinallyStatements.Add(newCodeSnippetStatement("//做些清理工作"));

ret.FinallyStatements.Add(newCodeSnippetStatement("return;"));

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:

try

{

 throw new Exception();;

} catch (System.Data.DataException dataException)

{

MessageBox.Show("数据库错误!");

} catch (System.Exception ex)

{

MessageBox.Show("未知的错误!");

} finally

{

//做些清理工作

return;

}

l,CodeVariableDeclarationStatement表示变量声明。

Type属性指定要声明的变量的类型。Name属性指定要声明的变量的名称。InitExpression属性是可选的,它指定创建变量后要赋予该变量的初始化表达式。

某些语言可以实现可选的变量初始化表达式,方法是在变量声明之后加入单独的赋值语句。

CodeVariableDeclarationStatement ret =new CodeVariableDeclarationStatement();

ret.Type =new CodeTypeReference(typeof(double));

ret.Name ="myVar";

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:double myVar;

加上赋值后

CodeVariableDeclarationStatement ret =new CodeVariableDeclarationStatement();

ret.Type =new CodeTypeReference(typeof(double));

ret.Name ="myVar";

ret.InitExpression =new CodeBinaryOperatorExpression(newCodePrimitiveExpression(2), CodeBinaryOperatorType.Multiply, new CodePrimitiveExpression(4));

codeProvider.GenerateCodeFromStatement(ret, tw, options);

输出的代码字符串为:double myVar = (2 * 4);

  

3, GenerateCodeFromMember方法

 MSDN描述:为指定的代码文档对象模型 (CodeDOM) 成员声明生成代码,并使用指定的选项将代码发送到指定的文本编写器。

通俗理解:将类的各种类型成员输出为代码字符串

a, CodeMemberField表示某种类型的字段的声明。

CodeMemberField ret =new CodeMemberField();

ret.Type =new CodeTypeReference(typeof(Int32));

ret.Attributes =MemberAttributes.Private;

ret.Name ="m_Number";

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:private int m_Number;

为字段上加注释

CodeMemberField ret =new CodeMemberField();

ret.Type =new CodeTypeReference(typeof(Int32));

ret.Attributes =MemberAttributes.Private;

ret.Name ="m_Number";

ret.Comments.Add(newCodeCommentStatement("这是一个测试用的字段",true));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个测试用的字段

private int m_Number;

为字段加上属性描述

CodeMemberField ret =new CodeMemberField();

ret.Type =new CodeTypeReference(typeof(Int32));

ret.Attributes =MemberAttributes.Private;

ret.Name ="m_Number";

ret.Comments.Add(newCodeCommentStatement("这是一个测试用的字段",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个测试用的字段

[System.SerializableAttribute(true)]

private int m_Number;

为字段加上初始化

CodeMemberField ret =new CodeMemberField();

ret.Type =new CodeTypeReference(typeof(Int32));

ret.Attributes =MemberAttributes.Private;

ret.Name ="m_Number";

ret.Comments.Add(newCodeCommentStatement("这是一个测试用的字段",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

ret.InitExpression =new CodePrimitiveExpression(100); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个测试用的字段

[System.SerializableAttribute(true)]

private int m_Number = 100;

b, CodeMemberEvent表示一个类型的事件的声明。

CodeMemberEvent ret =new CodeMemberEvent();

ret.Attributes =MemberAttributes.Public;

ret.Name ="Click";

ret.Type =newCodeTypeReference (typeof (EventHandler<EventArgs>)); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public event System.EventHandler<System.EventArgs> Click;

为事件加上注释

CodeMemberEvent ret =new CodeMemberEvent();

ret.Attributes =MemberAttributes.Public;

ret.Name ="Click";

ret.Type =newCodeTypeReference (typeof (EventHandler<EventArgs>));

ret.Comments.Add(newCodeCommentStatement("这是一个Click事件",true)); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个Click事件

public event System.EventHandler<System.EventArgs> Click;

为事件加上属性

CodeMemberEvent ret =new CodeMemberEvent();

ret.Attributes =MemberAttributes.Public;

ret.Name ="Click";

ret.Type =newCodeTypeReference (typeof (EventHandler<EventArgs>));

ret.Comments.Add(newCodeCommentStatement("这是一个Click事件",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个Click事件

[System.SerializableAttribute(true)]

public event System.EventHandler<System.EventArgs> Click;

备注:以下两个成员我还没有搞清楚起什么作用,msdn上说的也不清楚,有人清楚的话请告诉我,谢谢

QQ:32354456 Email:diablohe@hotmail.com

ret.PrivateImplementationType =new CodeTypeReference(typeof(double));

ret.ImplementationTypes.Add(newCodeTypeReference(typeof(int))); 

c, CodeMemberMethod表示某种类型的方法的声明。

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public virtual int DoSomething()

{

}

注意到MemberAttributes.Public直接对应了public virtual,有些奇怪

这里有必要先穿插研究下MemberAttributes的各种标志的用法

c.1MemberAttributes定义类成员的成员属性标识符。

Msdn描述:

Final

在派生类中不能重写的成员。

Static

静态成员。在 Visual Basic中,这等效于Shared 关键字。

Override

重写基类成员的成员。

Const

常数成员。

New

新成员。

Overloaded

重载成员。某些语言(如 Visual Basic)要求显式指示重载成员。

Assembly

在同一程序集中任何类都可以访问的成员。

FamilyAndAssembly

可以在其类以及其在同一程序集中的派生类中访问的成员。

Family

可以在其类以及其派生类家族内访问的成员。

FamilyOrAssembly

可以在其类、其在任何程序集中的派生类以及在同一程序集的任何类中均访问的成员。

Private

私有成员。

Public

公共成员。

AccessMask

访问屏蔽。

ScopeMask

范围屏蔽。

VTableMask

VTable屏蔽。

注意:

没有Virtual 成员属性。在不将成员指定为Final 的情况下,通过将成员访问设置为Public (public virtual),在 Visual Basic 中为overrideable (constructor1)标识为 public 的代码语句是constructor1.Attributes = MemberAttributes.Public;)会清除可能已设置的所有其他标志。使用ScopeMask 掩码设置范围标志(AbstractFinalStaticOverrideConst)时,也应使用此模式。

设置方法属性为public而不是public virtual

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public int DoSomething()

{

}

为方法加上注释

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public| MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!,true));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法

public int DoSomething()

{

}

为方法加上注释

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法!

[System.SerializableAttribute(true)]

public int DoSomething()

{

}

为方法加上2个参数

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

arg1 .Type =newCodeTypeReference (typeof(Boolean));

arg1.Name ="arg1";

ret.Parameters.Add(arg1);

CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

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

arg2.Name ="arg2";

arg2.Direction =FieldDirection.Out;

ret.Parameters.Add(arg2);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法!

[System.SerializableAttribute(true)]

int System.Double.DoSomething(bool arg1, out int arg2)

{

}

为方法里加上执行代码

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

arg1 .Type =newCodeTypeReference (typeof(Boolean));

arg1.Name ="arg1";

ret.Parameters.Add(arg1);

CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

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

arg2.Name ="arg2";

arg2.Direction =FieldDirection.Out;

ret.Parameters.Add(arg2);

ret.Statements.Add(

newCodeSnippetStatement("if(arg1)arg2=200;/nelse arg2=0;/nreturn arg2;")); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法!

[System.SerializableAttribute(true)]

int System.Double.DoSomething(bool arg1, out int arg2)

{

if(arg1)arg2=200;

else arg2=0;

return arg2;

}

如果改方法是泛型方法,可以指定泛型参数

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

arg1 .Type =newCodeTypeReference (typeof(Boolean));

arg1.Name ="arg1";

ret.Parameters.Add(arg1);

CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

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

arg2.Name ="arg2";

arg2.Direction =FieldDirection.Out;

ret.Parameters.Add(arg2);

ret.Statements.Add(

newCodeSnippetStatement("if(arg1)arg2=200;/nelse arg2=0;/nreturn arg2;"));

CodeTypeParameter type1 =new CodeTypeParameter("TypeOne");

ret.TypeParameters.Add(type1);

CodeTypeParameter type2 =new CodeTypeParameter("TypeTwo");

ret.TypeParameters.Add(type2); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法!

[System.SerializableAttribute(true)]

int System.Double.DoSomething<TypeOne, TypeTwo>(bool arg1, out int arg2)

{

if(arg1)arg2=200;

else arg2=0;

return arg2;

}

为泛型参数指定约束条件

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.Comments.Add(newCodeCommentStatement("这是一个方法!",true));

CodeExpression constBool =new CodePrimitiveExpression(true);

CodeAttributeArgument attrArg =new CodeAttributeArgument(constBool);

CodeTypeReference attrType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attribute =new CodeAttributeDeclaration(attrType, attrArg);

ret.CustomAttributes.Add(attribute);

CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

arg1 .Type =newCodeTypeReference (typeof(Boolean));

arg1.Name ="arg1";

ret.Parameters.Add(arg1);

CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

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

arg2.Name ="arg2";

arg2.Direction =FieldDirection.Out;

ret.Parameters.Add(arg2);

ret.Statements.Add(

newCodeSnippetStatement("if(arg1)arg2=200;/nelse arg2=0;/nreturn arg2;"));

CodeTypeParameter type1 =new CodeTypeParameter("TypeOne");

type1.Constraints.Add(typeof (IList<int>)); 

ret.TypeParameters.Add(type1);

CodeTypeParameter type2 =new CodeTypeParameter("TypeTwo");

type2.Constraints.Add(typeof(ValueType));

ret.TypeParameters.Add(type2); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

///这是一个方法!

[System.SerializableAttribute(true)]

int System.Double.DoSomething<TypeOne, TypeTwo>(bool arg1, out int arg2)

 where TypeOne : System.Collections.Generic.IList<int>

 where TypeTwo : System.ValueType

{

if(arg1)arg2=200;

else arg2=0;

return arg2;

}

还有3个事件,为了轻装上阵,把代码回到最简单的第一步的基础上来测试

事件1PopulateParameters在首次访问Parameters集合时将激发的事件。

定义一个事件处理程序

staticvoid ret_PopulateParameters(object sender,EventArgs e)

{

CodeMemberMethod method = senderas CodeMemberMethod;

CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

arg1.Type =new CodeTypeReference(typeof(Boolean));

arg1.Name ="arg1";

method.Parameters.Add(arg1);

CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

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

arg2.Name ="arg2";

arg2.Direction =FieldDirection.Out;

method.Parameters.Add(arg2);           

}

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.PopulateParameters +=new EventHandler(ret_PopulateParameters);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public int DoSomething(bool arg1, out int arg2)

{

}

事件2:PopulateStatements在首次访问Statements集合时将激发的事件。

再定义一个事件处理程序

staticvoid ret_PopulateStatements(object sender,EventArgs e)

{

CodeMemberMethod method = senderas CodeMemberMethod;

method.Statements.Add(

newCodeSnippetStatement("if(arg1)arg2=200;/nelse arg2=0;/nreturn arg2;"));

}

CodeMemberMethod ret =new CodeMemberMethod();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.PopulateParameters +=new EventHandler(ret_PopulateParameters);

ret.PopulateStatements +=new EventHandler(ret_PopulateStatements);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public int DoSomething(bool arg1, out int arg2)

{

if(arg1)arg2=200;

else arg2=0;

return arg2;

}

事件3:PopulateImplementationTypes在首次访问ImplementationTypes集合时将激发的事件。

还每搞清楚起什么作用,知道的人告诉我下,谢谢

QQ:32354456 Email:diablohe@hotmail.com

ReturnTypeCustomAttributes获取该方法的返回类型的自定义属性。

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;

ret.Name ="DoSomething";

ret.ReturnType =newCodeTypeReference (typeof (int));

ret.ReturnTypeCustomAttributes.Add(

newCodeAttributeDeclaration(

newCodeTypeReference(typeof(SerializableAttribute)))); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

[return: System.SerializableAttribute()]

public int DoSomething()

{

}

备注:本人还没见过这种语法,也不清楚起什么用,知道的人告诉我下,谢谢

QQ:32354456 Email:diablohe@hotmail.com

PrivateImplementationType,ImplementationTypes这两个属性我也不清楚,知道的告诉我下,谢谢

d, CodeMemberProperty表示某种类型的属性的声明。

Type属性指定属性的数据类型。GetStatements属性包含属性的任何 get语句方法。SetStatements属性包含属性的任何 set语句方法。Parameters属性指定属性的任何参数,如索引器属性所需的参数。

CodeMemberProperty ret =new CodeMemberProperty();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;           

ret.Name ="MyProperty";

ret.HasGet =true;

ret.HasSet =true;           

return ret;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public void MyProperty

{

 get

 {

 }

 set

 {

 }

}

为getter和setter指定代码

CodeMemberProperty ret =new CodeMemberProperty();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;            

ret.Name ="MyProperty";

ret.HasGet =true;

ret.HasSet =true;

ret.GetStatements.Add(newCodeSnippetStatement("return m_MyProperty;"));

ret.SetStatements.Add(newCodeSnippetStatement("m_MyProperty=value;"));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public void MyProperty

public void MyProperty

{

 get

 {

return m_MyProperty;

 }

 set

 {

m_MyProperty=value;

 }

}

为属性增加参数

Msdn:通常情况下,属性不具有参数。CodeDom支持这方面的一个特例。对于具有特殊名称"Item"以及一个或多个参数的任何属性,它都为该类声明索引器属性。但是,并非所有语言都支持索引器声明。

CodeMemberProperty ret =new CodeMemberProperty();

ret.Attributes =MemberAttributes.Public | MemberAttributes.Final;           

ret.Name ="Item";

ret.HasGet =true;

ret.HasSet =true;

CodeParameterDeclarationExpression par=newCodeParameterDeclarationExpression ();

par.Type =newCodeTypeReference (typeof(int));

par.Name ="index";

ret.Parameters.Add(par);

ret.GetStatements.Add(newCodeSnippetStatement("return m_MyProperty;"));

ret.SetStatements.Add(newCodeSnippetStatement("m_MyProperty=value;"));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public void this[int index]

{

 get

 {

return m_MyProperty;

 }

 set

 {

m_MyProperty=value;

 }

}

注意:只有属性名为Item的时候参数才起作用,否则不起任何作用

e, CodeConstructor表示一个类型的实例构造函数的声明。

CodeConstructorret =new CodeConstructor ();

ret.Name ="dd";

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

private ()

{

}

没有函数名,怎么会事?哦,构造函数的名必须是与类名一致,不能自行定义的,那么就加入到类里试验下吧,找了下,就是CodeTypeDeclaration

加入类信息

CodeTypeDeclaration ret =new CodeTypeDeclaration("MyType");

CodeConstructor constructor =new CodeConstructor();

constructor.Name ="dd";

ret.Members.Add(constructor);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyType

{

   

 private MyType()

 {

 }

}

注意构造函数,达到了预期效果,哈哈

注意,构造函数和普通函数的唯一区别就是Name属性会被忽略,不起任何作用,所以其他属性也就不再逐一研究了

f, CodeTypeConstructor表示类的静态构造函数。

CodeTypeDeclaration ret =new CodeTypeDeclaration("MyType");

CodeTypeConstructor constructor =new CodeTypeConstructor();

constructor.Name ="dd";

ret.Members.Add(constructor);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyType

{

   

 static MyType()

 {

 }

}

其他属性类似普通函数,不再研究了

g, CodeTypeDeclaration表示类、结构、接口或枚举的类型声明。

本节最复杂的类型了,需要多花点精力,还是从最简单的开始

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

}

下面按字典顺序一个一个地研究各个属性

g-1, Attributes

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.Attributes =MemberAttributes.Private; 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

}

还是public,并不是预期的效果,接连测试其他几个都是public

Msdn是这样描述的:此属性用于指定类型成员的属性并没有说能指定类的属性,看来这个属性对类无效。

g-2BaseTypes获取类型的基类型。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.BaseTypes.Add(newCodeTypeReference(typeof(Stream)));

ret.BaseTypes.Add(newCodeTypeReference(typeof(IComparable)));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass : System.IO.Stream, System.IComparable

{

}

g-3 Comments代表注释

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.Comments.Add(newCodeCommentStatement("这是一个类的声明!"));

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

//这是一个类的声明!

public class MyClass

{

}

g-4 CustomAttributes自定义属性

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeTypeReference attType =new CodeTypeReference(typeof(SerializableAttribute));

CodeAttributeDeclaration attr =new CodeAttributeDeclaration(attType);

ret.CustomAttributes.Add(attr);   

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

[System.SerializableAttribute()]

public class MyClass

{

}

g-5IsClass获取或设置一个值,该值指示该类型是否是类或引用类型。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.IsClass =true;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

}

g-5IsEnum获取或设置一个值,该值指示该类型是否是枚举。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.IsEnum =true ;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public enum MyClass

{

}

g-6IsInterface获取或设置一个值,该值指示该类型是否是接口。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.IsInterface =true ;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public interface MyClass

{

}

g-7 IsPartial获取或设置一个值,该值指示该类型声明是完整的类型声明还是分部类型声明。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.IsPartial =true ;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public partial class MyClass

{

}

g-8 IsStruct获取或设置一个值,该值指示该类型是不是值类型(结构)。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.IsStruct =true ;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public struct MyClass

{

}

g-9 LinePragma此属性指示类型成员声明的位置。此属性可用于报告错误和进行调试。当基于模板文件生成代码时,类型成员声明的位置很有用。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.LinePragma =new CodeLinePragma();

ret.LinePragma.LineNumber = 5;

ret.LinePragma.FileName ="aaa.txt";

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

#line 5 "aaa.txt"

public class MyClass

{

}

   

#line default

#line hidden

未能搞明白用途,以后做代码生成器的时候再研究吧,有人知道用途的告诉我下,谢谢

QQ:32354456 Email:diablohe@hotmail.com

g-10 Members获取所表示的类型的类成员的集合。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeMemberField field =new CodeMemberField();

field.Name ="MyField";

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

ret.Members.Add(field);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 private int MyField;

}

加入一个方法

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeMemberMethod method=new CodeMemberMethod();

method.Name =" MyMethod";

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

ret.Members.Add(method);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 private intMyMethod()

 {

 }

}

加入一个属性

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeMemberProperty property =new CodeMemberProperty();

property.Name ="MyProperty";

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

property.HasGet =true;

ret.Members.Add(property);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 private int MyProperty

 {

 get

 {

 }

 }

}

加入一个事件

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeMemberEvent myEvent =new CodeMemberEvent();

myEvent.Name ="MyEvent";

myEvent.Type =new CodeTypeReference(typeof(EventHandler<EventArgs>));

ret.Members.Add(myEvent);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 private event System.EventHandler<System.EventArgs> MyEvent;

}

加入一个构造函数

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeConstructor cst =new CodeConstructor();

ret.Members.Add(cst);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 private MyClass()

 {

 }

}

加入类型构造函数

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

CodeTypeConstructor cst =new CodeTypeConstructor();

ret.Members.Add(cst);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass

{

   

 static MyClass()

 {

 }

}

g-11TypeAttributes获取或设置类型的属性。

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.TypeAttributes = System.Reflection.TypeAttributes.NestedAssembly;

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

internal class MyClass

{

}

TypeAttributes包含的类型很丰富,以后慢慢捉摸吧

g-12TypeParameters类型的模版参数,范型类定义用这个参数

CodeTypeDeclaration ret =new CodeTypeDeclaration();

ret.Name ="MyClass";

ret.TypeParameters.Add("T1");

ret.TypeParameters.Add("T2");

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

public class MyClass<T1, T2>

   

   

{

}

4,GenerateCodeFromNamespace方法

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

namespace MyNameSpace

{

   

}

加入注释

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

ret.Comments.Add(newCodeCommentStatement("这是一个命名空间!")); 

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

//这是一个命名空间!

namespace MyNameSpace

{

   

}

导入命名空间

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

CodeNamespaceImport import=newCodeNamespaceImport("System");

ret.Imports.Add(import);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

namespace MyNameSpace

{

 using System;

   

}

在该命名空间下定义类信息

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

CodeTypeDeclaration type1 =new CodeTypeDeclaration("MyType1");

ret.Types.Add(type1);

CodeTypeDeclaration type2 =new CodeTypeDeclaration("MyType2");

ret.Types.Add(type2);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

namespace MyNameSpace

{

   

   

 public class MyType1

 {

 }

   

 public class MyType2

 {

 }

}

还有3个事件

事件1 PopulateTypes

增加一个函数

staticvoid ret_PopulateTypes(object sender,EventArgs e)

{

CodeNamespace ret = senderas CodeNamespace;

CodeTypeDeclaration type1 =new CodeTypeDeclaration("MyType1");

ret.Types.Add(type1);

CodeTypeDeclaration type2 =new CodeTypeDeclaration("MyType2");

ret.Types.Add(type2);           

}

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

ret.PopulateTypes +=new EventHandler(ret_PopulateTypes);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

namespace MyNameSpace

{

   

   

 public class MyType1

 {

 }

   

 public class MyType2

 {

 }

}

事件2 PopulateImports

增加一个函数

staticvoid ret_PopulateImports(object sender,EventArgs e)

{

CodeNamespace ret = senderas CodeNamespace;

ret.Imports.Add(newCodeNamespaceImport("System"));              

}

  

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

ret.PopulateImports +=new EventHandler(ret_PopulateImports);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

namespace MyNameSpace

{

 using System;

   

}

  

事件3 PopulateComments

增加一个函数

staticvoid ret_PopulateComments(object sender,EventArgs e)

{

CodeNamespace ret = senderas CodeNamespace;

ret.Comments.Add(newCodeCommentStatement("这是一行注释!"));

}

  

CodeNamespace ret =new CodeNamespace();

ret.Name ="MyNameSpace";

ret.PopulateComments +=new EventHandler(ret_PopulateComments);

codeProvider.GenerateCodeFromMember(ret, tw, options);

输出的代码字符串为:

//这是一行注释!

namespace MyNameSpace

{

   

}

  

5,GenerateCodeFromType

这个版本实际上是GenerateCodeFromMemberd的一个阉割版本,在GenerateCodeFromMember版本的最后一部份已经详细研究了,不再继续研究

6, GenerateCodeFromCompileUnit为指定的代码文档对象模型 (CodeDOM) 编译单元生成代码,并使用指定的选项将代码发送到指定的文本编写器。

CodeCompileUnit ret =new CodeCompileUnit();

codeProvider. GenerateCodeFromCompileUnit(ret, tw, options);

输出的代码字符串为:

//------------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

输出的是默认的模版标题

a, AssemblyCustomAttributes获取生成的程序集的自定义属性集合。

CodeCompileUnit ret =new CodeCompileUnit();

CodeTypeReference ct =new CodeTypeReference(typeof(System.Data.DataTable));           

CodeAttributeDeclaration attr =new CodeAttributeDeclaration(ct);

ret.AssemblyCustomAttributes.Add(attr);

codeProvider. GenerateCodeFromCompileUnit(ret, tw, options);

输出的代码字符串为:

//------------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

   

   

[assembly: System.Data.DataTable()]

b, CodeNamespace获取命名空间的集合。

CodeCompileUnit ret =new CodeCompileUnit();

CodeTypeReference ct =new CodeTypeReference(typeof(System.Data.DataTable));           

CodeAttributeDeclaration attr =new CodeAttributeDeclaration(ct);

ret.AssemblyCustomAttributes.Add(attr);

CodeNamespace ns =new CodeNamespace("MyNameSpace");

ret.Namespaces.Add(newCodeNamespace(ns)); 

codeProvider. GenerateCodeFromCompileUnit(ret, tw, options);

输出的代码字符串为:

//------------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

   

   

[assembly: System.Data.DataTable()]

   

namespace MyNameSpace

{

   

}

c, ReferencedAssemblies获取引用的程序集。

从生成的源代码上看不出任何效果,估计在编译的时候才起作用,那就编译时在研究了

d, StartDirectives获取包含开始指令的CodeDirectiveCollection对象。

不明白意思,那就试验研究吧,CodeDom命名空间下看,

System.CodeDom..::.CodeDirective
      
System.CodeDom..::.CodeChecksumPragma
      
System.CodeDom..::.CodeRegionDirective

有两个子类,先研究简单的CodeRegionDirective,从字面上看与#region有关,就从它下手了

d-1 ,CodeRegionDirective

CodeCompileUnit ret =new CodeCompileUnit();

CodeRegionDirective dc=newCodeRegionDirective ();

dc.RegionText ="这里是一个Region!";

dc.RegionMode =CodeRegionMode.Start;

ret.StartDirectives.Add(dc);

codeProvider. GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

#region这里是一个Region!

//------------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

将RegionMode换成end看看

CodeCompileUnit ret =new CodeCompileUnit();

CodeRegionDirective dc=newCodeRegionDirective ();

dc.RegionText ="这里是一个Region!";

dc.RegionMode =CodeRegionMode.End;

ret.StartDirectives.Add(dc);

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

#endregion

//----------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//----------------------------------------------------------------------------

换成None呢?

CodeCompileUnit ret =new CodeCompileUnit();

CodeRegionDirective dc=newCodeRegionDirective ();

dc.RegionText ="这里是一个Region!";

dc.RegionMode =CodeRegionMode.None;

ret.StartDirectives.Add(dc);

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

//-------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//-------------------------------------------------------------------

哦,原来如此!CodeRegionDirective就是这个意思

那么搭配EndDirectives一起使用呢

CodeCompileUnit ret =new CodeCompileUnit();

CodeRegionDirective dc=newCodeRegionDirective ();

dc.RegionText ="这里是一个Region!";

dc.RegionMode =CodeRegionMode.Start;

ret.StartDirectives.Add(dc);

dc=newCodeRegionDirective ();

dc.RegionMode =CodeRegionMode .End;

ret.EndDirectives.Add(dc);

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

#region这里是一个Region!

//--------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//--------------------------------------------------------

   

   

#endregion

这应该就是CodeRegionDirective的用法了

d-2,CodeChecksumPragma表示代码校验和杂注代码实体。

MSDN也太抽象了吧

CodeCompileUnit ret =new CodeCompileUnit();

CodeChecksumPragma dc =new CodeChecksumPragma();

ret.StartDirectives.Add(dc);

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

#pragma checksum "" "{00000000-0000-0000-0000-000000000000}" ""

//-----------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//-----------------------------------------------------------------------

什么意思?把属性设置上看看

CodeCompileUnit ret =new CodeCompileUnit();

CodeChecksumPragma dc =new CodeChecksumPragma();

dc.FileName ="aa.txt";

dc.ChecksumAlgorithmId =Guid.NewGuid();

dc.ChecksumData =new byte[] { 1, 2, 3, 4,5,6,7 };

ret.StartDirectives.Add(dc);

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

#pragma checksum "aa.txt" "{0e627ca7-f0da-42fe-b359-e7c21ca4cb9a}" "010203040506

07"

//------------------------------------------------------------------------------

   

// <auto-generated>

//    此代码由工具生成。

//    运行库版本:2.0.50727.3603

//

//    对此文件的更改可能会导致不正确的行为,并且如果

//    重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

还是不懂,对C#的宏意思很清楚了请告诉我下,谢谢

QQ:32354456 Email:diablohe@hotmail.com

  

该总结下了,关于代码生成的相关内容[GenerateCode***]大概就这么多了,如有遗漏,请告知下,我再学习!

以上所有的学习都是针对C#语言,当然可以针对各种语言,只需要使用对应得CodeDomProvider就可以了。

学了这么多,感觉这个模型还是很有用的,以后可以把这个功能集成到自己的程序里,根据业务逻辑生成CodeDom模型的框架,生成代码文件,然后可以修改代码文件,编译到自己的程序集合里,为用户提供强大而方便的插件功能,应该还是很爽阿!

实战一下吧!

我希望自动生成一个代码框架如下(事先一个观察者模式的代码框架吧),目标如下:

namespace CodeDomPrj

{

   using System;

   using System.Collections.Generic;

   using System.Linq;

   using System.Text;

   // 被观察者的实体对象

   public classSubject

   {

       private String _name;

       public virtualString Name

       {

           get{return _name;}

           set{

               _name = value;

               if ((NameChanged != null))

               {

                   this.NameChanged(this,new NameChangedEventArgs(Name));

               }

           }

       }

       public eventEventHandler<NameChangedEventArgs> NameChanged;

       public classNameChangedEventArgs : EventArgs

       {

           private String _name;

           public NameChangedEventArgs(String name)

           {

               this._name = name;

           }

           public virtualString Name

           {

               get{return _name;}

           }

       }

   }

   

   // 观察者

   public classObserver

   {

       private Subject _subject;

       public Observer(Subject subject)

       {

           _subject = subject;

           Subject.NameChanged += new EventHandler<Subject.NameChangedEventArgs>(this.Subject_NameChanged);

       }

       public virtualSubject Subject

       {

           get{return _subject;}

       }

   

       private void Subject_NameChanged(object sender,Subject.NameChangedEventArgs e)

       {

           Console.WriteLine(e.Name);

       }

   }

}

下面就开始了

//namespace CodeDomPrj

CodeNamespace ns =new CodeNamespace("CodeDomPrj");

   

//   using System;

//   using System.Collections.Generic;

//   using System.Linq;

//   using System.Text;

CodeRegionDirective importStart =new CodeRegionDirective();

importStart.RegionMode =CodeRegionMode.Start;

CodeNamespaceImport import =new CodeNamespaceImport("System");

ns.Imports.Add(import);

import =new CodeNamespaceImport("System.Collections.Generic");

ns.Imports.Add(import);

import =new CodeNamespaceImport("System.Linq");

ns.Imports.Add(import);

import =new CodeNamespaceImport("System.Text");

ns.Imports.Add(import);

//   // 被观察者的实体对象

//   public class Subject

CodeTypeDeclaration Subject =new CodeTypeDeclaration();

Subject.Name ="Subject";

Subject.Comments.Add(newCodeCommentStatement("被观察者的实体对象"));

Subject.TypeAttributes = System.Reflection.TypeAttributes.Public;

   

{

   //        public class NameChangedEventArgs : EventArgs

   CodeTypeDeclaration NameChangedEventArgs =new CodeTypeDeclaration();

   NameChangedEventArgs.TypeAttributes = System.Reflection.TypeAttributes.Public;

   NameChangedEventArgs.BaseTypes.Add(new CodeTypeReference("EventArgs"));

   NameChangedEventArgs.Name = "NameChangedEventArgs";

   //            private String _name;

   CodeMemberField _name = new CodeMemberField("String","_name");

   NameChangedEventArgs.Members.Add(_name);

//           public virtual String Name

   CodeMemberProperty Name = new CodeMemberProperty();

   Name.Name = "Name";

   Name.HasGet = true;

   Name.Attributes = MemberAttributes.Public |MemberAttributes.VTableMask;

Name.Type = new CodeTypeReference("String");

//               get{return _name;}

   CodeMethodReturnStatement Return = new CodeMethodReturnStatement();

   Return.Expression = new CodeVariableReferenceExpression("_name");

   Name.GetStatements.Add(Return);

   NameChangedEventArgs.Members.Add(Name);

   //            public NameChangedEventArgs(String name)

   CodeConstructor cst = new CodeConstructor();

   cst.Attributes = MemberAttributes.Public;

   cst.Parameters.Add(new CodeParameterDeclarationExpression("String","name"));

   //                this._name = name;

   CodeFieldReferenceExpression left = new CodeFieldReferenceExpression(newCodeThisReferenceExpression(), "_name");

   CodeVariableReferenceExpression right =new CodeVariableReferenceExpression("name");

   CodeAssignStatement ass =new CodeAssignStatement();

   ass.Left = left;

   ass.Right = right;

   cst.Statements.Add(ass);

   NameChangedEventArgs.Members.Add(cst);

   Subject.Members.Add(NameChangedEventArgs);

}

{

   //        private String _name;

   CodeMemberField _name = new CodeMemberField("String","_name");

   Subject.Members.Add(_name);

   //        public virtual String Name

   CodeMemberProperty Name = new CodeMemberProperty();

   Name.Name = "Name";

   Name.HasGet = true;

   Name.HasSet = true;

   Name.Attributes = MemberAttributes.Public |MemberAttributes.VTableMask;

   Name.Type = new CodeTypeReference("String");

   //            get{return _name;}

   CodeMethodReturnStatement Return = new CodeMethodReturnStatement();

   Return.Expression = new CodeVariableReferenceExpression("_name");

   Name.GetStatements.Add(Return);

   //                _name = value;

   CodeVariableReferenceExpression _nameRef =new CodeVariableReferenceExpression("_name");

   CodeVariableReferenceExpression valueRef =new CodeVariableReferenceExpression("value");

   CodeAssignStatement assign = new CodeAssignStatement();

   assign.Left = _nameRef;

   assign.Right = valueRef;

   Name.SetStatements.Add(assign);

   //                if ((NameChanged != null))

   CodeConditionStatement ifCon = new CodeConditionStatement();

   CodeBinaryOperatorExpression condition =new CodeBinaryOperatorExpression();

   condition.Left = new CodeVariableReferenceExpression("NameChanged");

   condition.Right = new CodePrimitiveExpression(null);

   condition.Operator = CodeBinaryOperatorType.IdentityInequality;

   ifCon.Condition = condition;

   //                    this.NameChanged(this, new NameChangedEventArgs(Name));

   CodeEventReferenceExpression ev = new CodeEventReferenceExpression();

   ev.TargetObject = new CodeThisReferenceExpression();

   ev.EventName = "NameChanged";

   CodeDelegateInvokeExpression inv = new CodeDelegateInvokeExpression();

   inv.TargetObject = ev;    

   inv.Parameters.Add(new CodeThisReferenceExpression());

   inv.Parameters.Add(new CodeObjectCreateExpression(new CodeTypeReference("NameChangedEventArgs"),new CodeVariableReferenceExpression("Name")));

   ifCon.TrueStatements.Add(inv);

   

   //        public event EventHandler<NameChangedEventArgs> NameChanged;

   CodeMemberEvent evn = new CodeMemberEvent();

   evn.Attributes = MemberAttributes.Public;

   evn.Name = "NameChanged";

   evn.Type = new CodeTypeReference("EventHandler<NameChangedEventArgs>");

   Subject.Members.Add(evn);

   Name.SetStatements.Add(ifCon);

   Subject.Members.Add(Name);

   ns.Types.Add(Subject);

}

   

//   // 观察者

//   public class Observer

CodeTypeDeclaration Observer =new CodeTypeDeclaration();

Observer.IsClass =true;

Observer.TypeAttributes = System.Reflection.TypeAttributes.Public;

Observer.Name ="Observer";

Observer.Comments.Add(newCodeCommentStatement("观察者"));

{

   //        private Subject _subject;

   CodeMemberField _field = new CodeMemberField();

   _field.Name = "_subject";

   _field.Type = new CodeTypeReference("Subject");

   Observer.Members.Add(_field);

   //        public virtual Subject Subject

   CodeMemberProperty property = new CodeMemberProperty();

   property.Name = "Subject";

   property.Type = new CodeTypeReference("Subject");

   property.Attributes = MemberAttributes.Public |MemberAttributes.VTableMask;

   property.HasGet = true;

   //            get{return _subject;}

   CodeMethodReturnStatement returnSub = new CodeMethodReturnStatement();

   returnSub.Expression = new CodeVariableReferenceExpression("_subject");

   property.GetStatements.Add(returnSub);

   Observer.Members.Add(property);

   

   //        public Observer(Subject subject)

   CodeConstructor cst = new CodeConstructor();

   cst.Attributes = MemberAttributes.Public |MemberAttributes.VTableMask;

   CodeParameterDeclarationExpression arg =new CodeParameterDeclarationExpression();

   arg.Type = new CodeTypeReference("Subject");

   arg.Name = "subject";

   cst.Parameters.Add(arg);

   //            _subject = subject;

   CodeVariableReferenceExpression left = new CodeVariableReferenceExpression("_subject");

   CodeVariableReferenceExpression right =new CodeVariableReferenceExpression("subject");

   CodeAssignStatement assign = new CodeAssignStatement();

   assign.Left = left;

   assign.Right = right;

   cst.Statements.Add(assign);

   //            Subject.NameChanged += new EventHandler<Subject.NameChangedEventArgs>(this.Subject_NameChanged);

   CodeAttachEventStatement attach = new CodeAttachEventStatement();

   CodeEventReferenceExpression ev=newCodeEventReferenceExpression ();

   ev.TargetObject =new CodeVariableReferenceExpression("Subject");

   ev.EventName ="NameChanged";

   attach.Event = ev;

   CodeDelegateCreateExpression listen = new CodeDelegateCreateExpression();

   listen.MethodName = "Subject_NameChanged";

   listen.TargetObject = new CodeThisReferenceExpression();

   listen.DelegateType = new CodeTypeReference("EventHandler<Subject.NameChangedEventArgs>");

   attach.Listener = listen;               

   cst.Statements.Add(attach );

   Observer.Members.Add(cst);

   //        private void Subject_NameChanged(object sender, Subject.NameChangedEventArgs e)

   CodeMemberMethod method = new CodeMemberMethod();

   method.Name = "Subject_NameChanged";

   CodeParameterDeclarationExpression arg1 =new CodeParameterDeclarationExpression();

   arg1.Name = "sender";

   arg1 .Type =new CodeTypeReference (typeof (object ));

   method.Parameters.Add(arg1);

   CodeParameterDeclarationExpression arg2 =new CodeParameterDeclarationExpression();

   arg2.Name = "e";

   arg2.Type = new CodeTypeReference("Subject.NameChangedEventArgs");

   method.Parameters.Add(arg2);

   //            Console.WriteLine(e.Name);

   CodeMethodInvokeExpression refM = new CodeMethodInvokeExpression();

   refM.Method = new CodeMethodReferenceExpression();

   refM.Method.TargetObject = new CodeTypeReferenceExpression("Console");

   refM.Method.MethodName = "WriteLine";

   

   CodePropertyReferenceExpression arg3 = new CodePropertyReferenceExpression();

   arg3.TargetObject = new CodeVariableReferenceExpression("e");

   arg3.PropertyName = "Name";

   CodeVariableReferenceExpression aa = new CodeVariableReferenceExpression();

   aa.VariableName = "e.Name";

refM.Parameters.Add(aa); 

   

   method.Statements.Add(refM);

   Observer.Members.Add(method);

}

ns.Types.Add(Observer);

CodeCompileUnit ret =new CodeCompileUnit();

ret.Namespaces.Add(ns);

return ret;

}

codeProvider.GenerateCodeFromCompileUnit (ret, tw, options);

输出的代码字符串为:

结果台长就不累赘了!

从生成的结果来看,除了排版有少量的不一致以外,符合预期结果!

以上的所有内容综合起来算是Codom模型的一个方面的功能,这个方面代表一个从模型到代码的过程!

下面就开始研究CodeDom的另一方面,从代码到模型的过程!

7, Parse方法,将从指定文本流读取的代码编译进CodeCompileUnit

通俗地理解就是根据代码文件生成CodeDom模型.

假设代码文件内容如下

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace CodeDomPrj

{

   class codetext

   {

       public int i = 0;

       public string ss {get; set; }

       public void aa() { }

   }

}

用下面的代码测试

using (TextReader tr =new StringReader(@"../codetext.cs"))

{

    CodeCompileUnit ccu = codeProvider.Parse(tr);

}

得到的却是下面的结果,懊恼,可恶的Microsoft,竟然不提供解析器!

试验了所有的codeProvider,结果都是一样,这绝对是微软故意搞的,怎么办?自己写解析器,这是编译器的功能,以前只写过简单的编译程序,很没有信心,这玩意真的很需要功底,看起来简单,实现起来却问题一大堆!

网上搜索了下,有一个开源的.Net的IDE开发环境SharpDeveloper,这里有一个IParser接口,值得学习

项目中应用ICSharpCode.NRefactory.dll,位于SharpDeveloper的程序集中,导入两个命名空间

using ICSharpCode.NRefactory;

using ICSharpCode.NRefactory.Visitors;

using (TextReader tr =new StreamReader(@"../../codetext.cs"))

{              

   IParser parser=ParserFactory.CreateParser(SupportedLanguage.CSharp, tr);

   parser.Parse();

   CodeDomVisitor vis = new CodeDomVisitor();

   vis.VisitCompilationUnit(parser.CompilationUnit, null);

   CodeCompileUnit ccu= vis.codeCompileUnit;

}

观察ccu里面的内容,正是所需要的结构!

感谢无私奉献的老外,鄙视某些当宝贝卖钱的!

不知道在自己的程序里使用这个程序集是否涉及到版权问题!

以上是CodeDom的另一方面,微软并没有提供这方面的功能,使用上面内容的请注意版权问题。

再次感谢这些默默无闻无私奉献的老外!

下面研究CodeDom的最后一个方面,就是编译

8,CompileAssemblyFromSource从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。

options

类型:System.CodeDom.Compiler..::.CompilerParameters

一个CompilerParameters对象,它指示此编译的编译器设置。

sources

类型:array<System..::.String>[]()[]要编译的源代码字符串的数组。

首先看编译参数设置的问题,这一点MSDN上说的很明白,直接引用过来看看就明白了

CompilerParameters表示用于调用编译器的参数。

MSDN详细描述(整理后):

表示ICodeCompiler接口的设置和选项的CompilerParameters 对象。

1GenerateEcecutable

正在编译可执行程序,则必须将GenerateExecutable属性设置为true。当GenerateExecutable设置为false 时,编译器将生成一个类库。默认情况下,初始化新的CompilerParameters 时,它的GenerateExecutable属性被设置为false

2CodeEntryPointMethod

要从 CodeDOM图形编译可执行文件,则必须在该图形中定义CodeEntryPointMethod。如果有多个代码入口点,则可以通过如下方法指示定义要使用的入口点的类:将MainClass属性设置为该类的名称。

3OutputAssembly

OutputAssembly属性中指定输出程序集的文件名。如果不指定,则使用默认的输出文件名。

要在生成的程序集中包括调试信息,请将IncludeDebugInformation属性设置为true

4ReferenedAssemblies

项目引用了任何程序集,则必须将引用的程序集名称指定为StringCollection中的项,设置到在调用编译时使用的CompilerParameters ReferencedAssemblies属性中。

5,GenerateInMemory

通过将GenerateInMemory属性设置为true,可以编译写入内存而不是磁盘中的程序集。当在内存中生成程序集时,代码可从CompilerResultsCompiledAssembly属性中获取生成的程序集的引用。

如果程序集被写入到磁盘中,则可以从CompilerResultsPathToAssembly属性获取到生成的程序集的路径。

6,WarningLevel

要指定暂停编译的警告级别,请将WarningLevel属性设置为一个用来表示暂停编译的警告级别的整数。也可以通过将TreatWarningsAsErrors属性设置为true,将编译器配置成在遇到警告时暂停编译。

7,CompilerOptions

要指定调用编译进程时使用的自定义命令行参数字符串,请在CompilerOptions属性中设置该字符串。

8,UserToken

如果在调用编译器进程时需要 Win32安全标记,请在UserToken属性中指定该标记。

9,EmbeddedResources

若要将 .NET Framework资源文件包含到已编译的程序集中,请将这些资源文件的名称添加到EmbeddedResources属性中。

10,LinkedResources

若要引用另一程序集中的 .NET Framework资源,请将这些资源文件的名称添加到LinkedResources属性中。

11,Win32Resource

若要将一个 Win32资源文件包含到已编译的程序集中,请在Win32Resource属性中指定该 Win32资源文件的名称。

下面的代码片段就作为测试代码

namespace simpleapp

{

   using System;

   using System.Data;

   class Program

   {

       static void Main(string[] args)

       {

           DataTable dt = new DataTable("testTable");

           Console.WriteLine("Hello world One!");

       }

   }

   class Program2

   {

       static void Main(string[] args)

       {

           Console.WriteLine("Hello world Two!");

       }

   }

}

CompileAssemblyFromFile从包含在指定文件中的源代码,使用指定的编译器设置编译程序集

CompilerParameters cp =new CompilerParameters();

cp.GenerateExecutable =true;

cp.OutputAssembly ="aa.exe";

cp.IncludeDebugInformation =true;

cp.ReferencedAssemblies.Add("System.dll");

cp.ReferencedAssemblies.Add("System.Data.dll");

cp.ReferencedAssemblies.Add("System.Xml.dll");

cp.GenerateInMemory =false;

cp.WarningLevel = 3;

cp.TreatWarningsAsErrors =false;

cp.CompilerOptions ="/optimize";

cp.MainClass ="simpleapp.Program";

   

CompilerResults ret = codeProvider.CompileAssemblyFromFile(cp,

newstring []{@"D:/何国栋/工作流学习/simpleapp/simpleapp/Program.cs"});

测试结果:正确生成了aa.exe

运行aa.exe看看

哈哈,第一个编译顺利成功!

CompileAssemblyFromDom基于包含在CodeCompileUnit对象的指定数组中的 System.CodeDom树,使用指定的编译器设置编译程序集。

CompilerParameters cp =new CompilerParameters();

cp.GenerateExecutable =true;

cp.OutputAssembly ="aa.exe";

cp.IncludeDebugInformation =true;

cp.ReferencedAssemblies.Add("System.dll");

cp.ReferencedAssemblies.Add("System.Data.dll");

cp.ReferencedAssemblies.Add("System.Xml.dll");

cp.GenerateInMemory =false;

cp.WarningLevel = 3;

cp.TreatWarningsAsErrors =false;

cp.CompilerOptions ="/optimize";

cp.MainClass ="simpleapp.Program";

CodeCompileUnit ccu =null;

using (TextReader tr =

newStreamReader(@"D:/何国栋/工作流学习/simpleapp/simpleapp/Program.cs"))

{

IParser parser =ParserFactory.CreateParser(SupportedLanguage.CSharp, tr);

parser.Parse();

CodeDomVisitor vis =new CodeDomVisitor();

vis.VisitCompilationUnit(parser.CompilationUnit,null);

ccu = vis.codeCompileUnit;

}

CompilerResults ret = codeProvider.CompileAssemblyFromDom(cp, ccu);

很顺利,一次成功!下面最后一个版本了

CompileAssemblyFromSource从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。

CompilerParameters cp =new CompilerParameters();

cp.GenerateExecutable =true;

cp.OutputAssembly ="aa.exe";

cp.IncludeDebugInformation =true;

cp.ReferencedAssemblies.Add("System.dll");

cp.ReferencedAssemblies.Add("System.Data.dll");

cp.ReferencedAssemblies.Add("System.Xml.dll");

cp.GenerateInMemory =false;

cp.WarningLevel = 3;

cp.TreatWarningsAsErrors =false;

cp.CompilerOptions ="/optimize";

cp.MainClass ="simpleapp.Program";

string[] codes =new string[]

{

       "namespace simpleapp",

       "{",

       "    using System;",

       "    class Program",

       "    {",

       "        static void Main(string[] args)",

       "        {",

       "            Console.WriteLine(/"Hello world One!/"); ",

       "        }",

       "    }",

       "    class Program2",

       "    {",

       "        static void Main(string[] args)",

       "        {",

       "            Console.WriteLine(/"Hello world Two!/");",

       "        }",

       "    }",

       "}"

};

CompilerResults ret = codeProvider.CompileAssemblyFromSource(cp, codes);

foreach (CompilerError errin ret.Errors)

{

   Console.WriteLine("{0}行{1}列,{2}", err.Line,err.Column,  err.ErrorText); 

}

情况不秒,我理解的意思是第二个参数就是源代码的字符串数组啊,难道是这样?

"namespace simpleapp/n"+

"{/n"+

"   using System;/n"+

"   class Program/n"+

"   {/n"+

"       static void Main(string[] args)/n"+

"       {/n"+

"           Console.WriteLine(/"Hello world One!/"); /n"+

"       }/n"+

"   }/n"+

"   class Program2/n"+

"   {/n"+

"       static void Main(string[] args)/n"+

"       {/n"+

"           Console.WriteLine(/"Hello world Two!/");/n"+

"       }/n"+

"   }/n"+

"}"

测试,成功,哈哈!

没想到真的是这样,数组的每一个元素不是代表一行代码,而是要代表一个完整的文件!

CodeDom的基本模型学习完毕,还有几个其他的方法,要么和设计器有关,要么很简单,名字上就可以看出来。和设计器有关的内容下一步制作IDE开发环境的时候再研究吧!

休息几天,继续研究我的Winform设计器和工作流设计器,谁有这方面经验的请多指教,工作流设计器原型已经调试好了,需要进一步完善!Winform设计器还在收集资料学习中,谁有这方面资料请贡献出来参考参考,代表所有学生感谢了!

求关于System.CompomentModel和System.Drawing.Desion里面内容的详细资料,权威书籍,请各位介绍一点,本人学习后继续把心得体会记录下来!

QQ:32354456

Email:diablohe@hotmail.com

posted @ 2015-10-23 22:11  赛提斯特  阅读(1744)  评论(0编辑  收藏  举报