最近在自己实践一个异常扑捉设计,在模块中我觉得该给用户提供的是代码生成工具,而不是怎么去做,再自己去写代码。现在代码模板生成的有很多
但我选择了用微软的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.生成的代码
上面代码很简单,我特意也把注释写上了,所以不用一句一句的讲解了,哈哈。
CodeDom提供了很多操作,如定义类,还可以定义结构、枚举;类里面的方法、属性、字段及构造函数;定义Attribute;事件及委托;赋值、条件(if)、循环(for)语句;变量声明;异常处理语句;甚至还可以加注释以及块(#region #endregion)。除了分支选择switch、while,dowhile循环及break、continue没发现外,其他大多数东西都有,着已经足够了,程序三大结构,足以实现很多的代码生成了。
msdn CodeDom参考:http://msdn.microsoft.com/zh-cn/library/f1dfsbhc(VS.80).aspx
本文转自 破狼 51CTO博客,原文链接:http://blog.51cto.com/whitewolfblog/834311,如需转载请自行联系原作者