微软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版中,代码提供程序包含CodeDomProvider、ICodeGenerator、ICodeParser和ICodeCompiler的实现。

在 .NET Framework 2.0中,CreateGenerator、CreateParser和CreateCompiler方法已过时,ICodeGenerator和ICodeCompiler 的方法在CodeDomProvider 类中直接可用。


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


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


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

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

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

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

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


CompilerInf的IsCodeDomProviderTypeValid为另一重要属性,用处描述为

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


备注:生成CodeDomProvider实例方式1:Compilerinf的CreateProvider


CompilerInf的GetLanguages方法返回一个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


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


本段学习的代码段

 

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上有备注如下)

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

7和8:准备好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:[email protected]

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个事件,为了轻装上阵,把代码回到最简单的第一步的基础上来测试


事件1:PopulateParameters在首次访问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:[email protected]


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:[email protected]


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:[email protected]


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:[email protected]


 


该总结下了,关于代码生成的相关内容[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
对象。

1,GenerateEcecutable

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

2,CodeEntryPointMethod

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

3,OutputAssembly

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

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

4,ReferenedAssemblies

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

5,GenerateInMemory

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

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

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:[email protected]

时间: 2024-10-10 00:28:34

微软CodeDom模型学习笔记(全)的相关文章

DOM事件模型学习笔记

下面的内容属于阅读笔记,其中涉及大量内容来自于PPK的博客的内容,如果你要跟随我的脚步领略大家风采,那么就从Introduction to Events开始阅读吧. 现代的前端开发应该是会严格遵守 html 展示文档内容构成,css 渲染页面效果,javascript 提供交互 浏览器提供交互行为可以追溯到Netscape公司在其第二个版本中支持javascript语言,随后其与微软之间的浏览器大战,以及w3c标准制定的落后,导致至今一直被诟病的浏览器兼容问题,而这些不兼容中关于DOM事件模型的

【点击模型学习笔记】Predicting Clicks_Estimating the Click-Through Rate for New Ads_MS_www2007

概要: 微软研究院的人写的文章,提出用逻辑回归来解决ctr预估问题,是以后ctr的经典解决方案,经典文章. 具体内容: 名词: CPC -- cost per click CTR -- click through rate 1. 研究初衷 搜索引擎主要靠商业广告收入,在广告位上面打广告,用户点击,之后广告商付费.在通用搜索引擎,通常广告位置是在搜索结果之前,或者在搜索结果右边. 商业广告收入 = pClick * CPC 要提升广告收入,关键问题是在有限的广告为上面,放什么广告?很自然的想法就是

【点击模型学习笔记】A survey on click modeling in web search_Lianghao Li_ppt

是一篇综述性质的ppt. 主要内容: 对搜索中的广告点击预测,总结学术界的研究成果. 搜索广告主要展示位为:1. 搜索结果页面最上侧:2. 搜索结果右侧. 研究意义:广告点击次数直接影响收入 问题抽象:对于某个query q,和某个广告ad,预测用户对它们的点击率. 具体内容: 1. 最简单的点击模型:通过点击次数来预测,计算公式为 P = #count of clicks / #count of impressions(展现) 缺点:点击受到用户浏览行为的影响:对于长尾query和ad,存在冷

概率图模型学习笔记(二)贝叶斯网络-语义学与因子分解

概率分布(Distributions) 如图1所示,这是最简单的联合分布案例,姑且称之为学生模型. 图1 其中包含3个变量,分别是:I(学生智力,有0和1两个状态).D(试卷难度,有0和1两个状态).G(成绩等级,有1.2.3三个状态). 表中就是概率的联合分布了,表中随便去掉所有包含某个值的行,就能对分布表进行缩减. 例如可以去掉所有G不为1的行,这样就只剩下了1.4.7.10行,这样他们的概率之和就不为1了,所以可以重新标准化(Renormalization).如图2所示. 图2 反之也可以

【点击模型学习笔记】Modeling contextual factors of click rates_MS_AAAI2007

概要 并没有觉得这是篇高质量的文章,很奇怪为什么能够发表在AAAI上面. 文章的创新点比较单薄:在传统点击率预测模型(LR)的基础上加入了两类新的特征,一个是位置特征,一个是广告上下文特征--即和它并排展示的其他广告的特征 具体内容 1. 建模 文章中,作者用了两种模型: (1)逻辑回归模型 作者用0-1特征,将位置信息作为一个种特征加入到模型当中:输出结果也是0-1二分类,表示用户是否点击了这个广告. 值得注意的是:作者认为,训练出来的模型参数,某个特征的系数值比较大,则这个特征也比较重要--

【点击模型学习笔记】Ad centric model discovery for redicting ads&#39; click through rate_ANT2013_Tencent

腾讯soso的人写的一篇文章,介绍soso广告系统的ctr预估技术.2013年的,应该反映了当前soso的ctr预估系统的情况. ANT会议质量一般,elsevier出版社出版.搞笑的是,文章摘要居然把论文模板上的这句话"Click here and insert your abstract text"原封不动的写在了第一句,并且就这样发表了! 主要内容: 描述soso搜索结果页面中广告点击率预测的系统实现. 具体内容: 1. 相关工作 Rechardson用逻辑回归来预测ctr ki

【点击模型学习笔记】广告点击率估算技术综述_华东师范大学学报2013

概要: 不是一篇高质量文章,不过是一篇还算不错的综述,而且时间够新(2013). 具体内容:按照文章原本内容顺序罗列 0. 介绍 * 赞助商广告:投放到搜索结果页面 * 情境广告:在网页某个位置上投放,一般由广告联盟介入 1. 广告点击率预测的应用背景 * 广告点击率一般比较低,能达到0.2%就已经是很好的投放了 * 大量的广告.查询都是很稀疏的 * 利用用户点击行为的,除了点击率预测,还有两个领域:搜索结果排序和推荐系统 * "Inferring Clickthrough Rates on A

【点击模型学习笔记】Inferring clickthrough rates on ads from click behavior on search results_wsdm2011

概要: 看这篇文章的初衷,是这篇文章回答了问题"在一个query的结果当中,给出多少个广告位合适?".文章不长,不过一路看下来,发现貌似不是native-english-speaker写的,细节说的不清楚,完全无法还原作者的工作思路.不过还是有那么一点儿收获的. 具体内容: 搜索主要的赚钱方式是在搜索结果当中嵌入广告,一般来讲是按照广告的点击次数来付费的.这样,就有一个趋势,如果想要赚钱多,就在搜索结果中越来越多的植入广告,使得广告的点击次数越来越多,则赚的钱就越来越多:不过,也有研究

Probability Latent Semantic Analysis (PLSA) 模型 学习笔记

Probability Latent Semantic Analysis (PLSA) 模型 学习笔记 PLSA是前面LSA的兄弟版,相比于LSA而言,PLSA定义了概率模型,而且每个变量以及相应的概率分布和条件概率分布都有明确的物理解释了.这篇博文我们分三部分来说PLSA:基本思想,EM算法推导,以及优缺点分析. 1.  PLSA的基本思想 PLSA是一种主题模型topic model,是针对文本中隐含的主题来建模的方法.PLSA就是给定了文档d之后,需要以一定的概率选择与文档相对应的主题z,