最近在自己实践一个异常扑捉设计,在模块中我觉得该给用户提供的是代码生成工具,而不是怎么去做,再自己去写代码。现在代码模板生成的有很多
但我选择了用微软的CODEDOM技术来实现,由于比较熟悉,以及感觉我将只用在.NET平台是已经够强大了。最近也总想写点博客,但是不知道写些什么,所以就准备写个CODEDOM的系列。仅是开篇,就写个简单的HelloWord程序吧。
CODEDOM在.NET Framework SDK文档里是这么讲述的:
.NET Framework 中包含一个名为“代码文档对象模型”(CodeDOM) 的机制,该机制使编写源代码的程序的开发人员可以在运行时,根据表示所呈现代码的单一模型,用多种编程语言生成源代码。
为表示源代码,CodeDOM 元素相互链接以形成一个数据结构(称为 CodeDOM 图),它以某种源代码的结构为模型。
System.CodeDom 命名空间定义可以表示源代码的逻辑结构(与具体的编程语言无关)的类型。System.CodeDom.Compiler 命名空间定义从 CodeDOM 图生成源代码的类型,和在受支持的语言中管理源代码编译的类型。编译器供应商或开发人员可以扩展受支持语言的集合。
还是先贴上代码:
using System;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
namespace CodeDomDemo1
{
class Program
{
static void Main( string [] args)
{
Program pro = new Program();
CodeNamespace nspace = pro.CreateCodeDomHelloDemo();
Console.WriteLine(pro.GengerCode(nspace));
string filename = " HelloWorld.exe " ;
CompilerResults result = pro.Execute(nspace,filename);
if (result.Errors.HasErrors) // 是否存在错误;
{
for ( int i = 0 ; i < result.Output.Count; i ++ )
Console.WriteLine(result.Output[i]);
for ( int i = 0 ; i < result.Errors.Count; i ++ )
Console.WriteLine(i.ToString() + " : " + result.Errors[i].ToString());
}
else
{
System.Diagnostics.Process.Start(filename); // 这里比较懒,不想动手去自己打开,呵呵;
}
Console.Read();
}
public CodeNamespace CreateCodeDomHelloDemo()
{
CodeMemberMethod method = new CodeMemberMethod(); // 方法声明;
method.Name = " SayHello " ; // 方法名
method.Attributes = MemberAttributes.Public | MemberAttributes.Final; // 属性
method.ReturnType = new CodeTypeReference( typeof ( string )); // 返回类型
method.Statements.Add( new CodeMethodReturnStatement( new CodePrimitiveExpression( " Hello from code! " ))); // 方法体,只有一句返回语句return "Hello from code!";
CodeEntryPointMethod main = new CodeEntryPointMethod(); // 主方法Main
main.Statements.Add( new CodeVariableDeclarationStatement( " HelloWord " , " hw " ,
new CodeObjectCreateExpression( " HelloWord " , new CodeExpression[] { }))); // 变量声明:HelloWord hw = new HelloWord();
CodeMethodInvokeExpression methodinvoke = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression( " hw " ), " SayHello " , new CodeExpression[]{});
main.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression( " System.Console " ), " WriteLine " , methodinvoke));
main.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression( " System.Console " ), " Read " )); // 两个方法调用:System.Console.WriteLine(hw.SayHello());
CodeTypeDeclaration helloword = new CodeTypeDeclaration( " HelloWord " ); // 类型Class声明
helloword.Attributes = MemberAttributes.Public;
helloword.Members.AddRange( new CodeTypeMember[]{method,main}); // 添加方法到clss
CodeNamespace nspace = new CodeNamespace( " HelloDemo1 " ); // 命名空间声明
nspace.Imports.Add( new CodeNamespaceImport( " System " )); // 引入程序命名空间:using System;
nspace.Types.Add(helloword); //
return nspace;
}
public string GengerCode(CodeNamespace nspace)
{
StringBuilder sb = new StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
CodeGeneratorOptions geneOptions = new CodeGeneratorOptions(); // 代码生成选项
geneOptions.BlankLinesBetweenMembers = false ;
geneOptions.BracingStyle = " C " ;
geneOptions.ElseOnClosing = true ;
geneOptions.IndentString = " " ;
CodeDomProvider.GetCompilerInfo( " c# " ).CreateProvider().GenerateCodeFromNamespace(nspace, sw, geneOptions); // 代码生成
sw.Close();
return sb.ToString();
}
public CompilerResults Execute(CodeNamespace nspace, string filename)
{
CodeCompileUnit unit = new CodeCompileUnit(); // code编译单元
unit.Namespaces.Add(nspace);
CodeDomProvider provider = CodeDomProvider.CreateProvider( " C# " );
CompilerParameters options = new CompilerParameters(); //
options.GenerateInMemory = false ; // 是否在内存中生成;
options.IncludeDebugInformation = true ; // 包含调试信息;
options.ReferencedAssemblies.Add( " System.dll " );
options.OutputAssembly = filename;
if (System.IO.Path.GetExtension(filename).ToLower() == " .exe " )
{
options.GenerateExecutable = true ; // true为可执行exe,false:dll
}
else
{
options.GenerateExecutable = false ; // true为可执行exe,false:dll
}
return provider.CompileAssemblyFromDom(options, unit); // 编译程序集
}
}
}
结果截图:1:生成的代码:
2:运行结果:
上面代码很简单,我特意也把注释写上了,所以不用一句一句的讲解了,哈哈。
CodeDom提供了很多操作,如定义类,还可以定义结构、枚举;类里面的方法、属性、字段及构造函数;定义Attribute;事件及委托;赋值、条件(if)、循环(for)语句;变量声明;异常处理语句;甚至还可以加注释以及块(#region #endregion)。除了分支选择switch、while,dowhile循环及break、continue没发现外,其他大多数东西都有,着已经足够了,程序三大结构,足以实现很多的代码生成了。
msdn CodeDom参考:http://msdn.microsoft.com/zh-cn/library/f1dfsbhc(VS.80).aspx
作者:破 狼
出处:http://www.cnblogs.com/whitewolf/
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客、博客园--破狼和51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2010/06/19/1760708.html