前一阶段一直在做一个基于VS.NET2k3的一个插件,大致功能是实现业务代码的自动生成。程序在前几天终于突破性的进展,所有的功能都能实现了。包括自动添加工程,引用,编译等。等再过些天,把代码进行优化一些(同时去除一些BUG,一直不明白,当产生几万行代码后,我的开发环境会全面崩溃了)再发布出来吧。昨天突然想到,现在产生的代码过于生,不能根据用户的选择来生成对应的语言的代码。如果死写的话,也太没意思了。想到以前曾看过MSDN里介绍过CODEDOM这玩意能生成各门语言的代码,能动态调用编译,于是快速将CODEDOM再看一次,果然能生成C#,VB,JSCRIPT的代码。不过刚开始研究,只写了一个小小的程序。不过也觉得很有意思的。这样的话,我只要将我的TOOLKIT重写一下就可以让不同的程序员根据自己的喜好生成对应的代码了(功能都是一样的。)
using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; using Microsoft.CSharp; using Microsoft.VisualBasic; using Microsoft.JScript; //这个示例演示如何使用System.CodeDom来建立一个HELLO World程序,将会根据用户的选择动态代码生成及编译的C#,VB,JScript版本的程序集
namespace CodeDOMTest { public class CodeDomExampleForm : System.Windows.Forms.Form { private System.Windows.Forms.Button run_button = new System.Windows.Forms.Button(); private System.Windows.Forms.Button compile_button = new System.Windows.Forms.Button(); private System.Windows.Forms.Button generate_button = new System.Windows.Forms.Button(); private System.Windows.Forms.TextBox textBox1 = new System.Windows.Forms.TextBox(); private System.Windows.Forms.ComboBox comboBox1 = new System.Windows.Forms.ComboBox(); private System.Windows.Forms.Label label1 = new System.Windows.Forms.Label(); private void generate_button_Click(object sender, System.EventArgs e) { CodeDomProvider provider = GetCurrentProvider(); CodeDomExample.GenerateCode(provider, CodeDomExample.BuildHelloWorldGraph()); StreamReader sr = new StreamReader("MyHello.cs"); textBox1.Text = sr.ReadToEnd(); sr.Close(); }
private void compile_button_Click(object sender, System.EventArgs e) { CodeDomProvider provider = GetCurrentProvider(); CompilerResults cr = CodeDomExample.CompileCode(provider, "MyHello.cs");
if(cr.Errors.Count > 0) { textBox1.Text = "编译文件出错: "+cr.PathToAssembly+": \r\n"; foreach(CompilerError ce in cr.Errors) textBox1.AppendText(ce.ToString()+"\r\n"); run_button.Enabled = false; } else { textBox1.Text = cr.PathToAssembly+" 编译成功"; run_button.Enabled = true; } }
private void run_button_Click(object sender, System.EventArgs e) { Process.Start("MyHello.exe"); } /// <summary> /// 根据用户的选择返回不同语言的代码生成器 /// </summary> /// <returns></returns> private CodeDomProvider GetCurrentProvider() { CodeDomProvider provider; switch((string)this.comboBox1.SelectedItem) { case "CSharp": provider = new CSharpCodeProvider(); break; case "Visual Basic": provider = new VBCodeProvider(); break; case "JScript": provider = new JScriptCodeProvider(); break; default: provider = new CSharpCodeProvider(); break; } return provider; } public CodeDomExampleForm() { this.SuspendLayout(); this.label1.Location = new System.Drawing.Point(395, 20); this.label1.Size = new Size(180, 22); this.label1.Text = "Select a programming language:"; this.comboBox1.Location = new System.Drawing.Point(560, 16); this.comboBox1.Size = new Size(190, 23); this.comboBox1.Name = "comboBox1"; this.comboBox1.Items.AddRange( new string[] { "CSharp", "Visual Basic", "JScript" } ); this.comboBox1.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right | System.Windows.Forms.AnchorStyles.Top; this.comboBox1.SelectedIndex = 0; this.generate_button.Location = new System.Drawing.Point(8, 16); this.generate_button.Name = "generate_button"; this.generate_button.Size = new System.Drawing.Size(120, 23); this.generate_button.Text = "Generate Code"; this.generate_button.Click += new System.EventHandler(this.generate_button_Click); this.compile_button.Location = new System.Drawing.Point(136, 16); this.compile_button.Name = "compile_button"; this.compile_button.Size = new System.Drawing.Size(120, 23); this.compile_button.Text = "Compile"; this.compile_button.Click += new System.EventHandler(this.compile_button_Click); this.run_button.Enabled = false; this.run_button.Location = new System.Drawing.Point(264, 16); this.run_button.Name = "run_button"; this.run_button.Size = new System.Drawing.Size(120, 23); this.run_button.Text = "Run"; this.run_button.Click += new System.EventHandler(this.run_button_Click); this.textBox1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right); this.textBox1.Location = new System.Drawing.Point(8, 48); this.textBox1.Multiline = true; this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(744, 280); this.textBox1.Text = ""; // CodeDomExampleForm this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(768, 340); this.MinimumSize = new System.Drawing.Size(750, 340); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.textBox1, this.run_button, this.compile_button, this.generate_button, this.comboBox1, this.label1 }); this.Name = "CodeDomExampleForm"; this.Text = "CodeDom Hello World Example"; this.ResumeLayout(false); }
protected override void Dispose( bool disposing ) { base.Dispose( disposing ); }
private void InitializeComponent() { this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); this.ClientSize = new System.Drawing.Size(448, 269); this.Name = "CodeDomExampleForm";
}
[STAThread] static void Main() { Application.Run(new CodeDomExampleForm()); } }
public class CodeDomExample {
public static CodeCompileUnit BuildHelloWorldGraph() { //建立一个代码容器 //CodeCompileUnit 包含以下几个集合:可以存储包含 CodeDOM 源代码图形的 CodeNamespace 对象的集合、 //项目引用的程序集的集合,以及项目程序集的属性集合。 CodeCompileUnit CompileUnit = new CodeCompileUnit();
// 声明一个名称空间 CodeNamespace MySample = new CodeNamespace("MySample"); // 将名称空间加入到代码容器 CompileUnit.Namespaces.Add( MySample ); // 导入一个名称空间 MySample.Imports.Add( new CodeNamespaceImport("System") );
// 声明一个类型 CodeTypeDeclaration Hello = new CodeTypeDeclaration("Hello"); // 将类型加入到容器的类型集合中 MySample.Types.Add(Hello); // 构造函数(并非必须) CodeConstructor con = new CodeConstructor(); con.Attributes = MemberAttributes.Public | MemberAttributes.Final; Hello.Members.Add(con); // 表示可执行文件的入口点方法,也就是一个程序的入口 CodeEntryPointMethod Start = new CodeEntryPointMethod(); // 建立一个代码调用的表达式 CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression( // 调用方法. System.Console.WriteLine new CodeTypeReferenceExpression("System.Console"), "WriteLine", // 给方法传一个基元数据类型的值 new CodePrimitiveExpression("Hello World!") ); // 将方法加入到方法中 Start.Statements.Add(new CodeExpressionStatement(cs1)); CodeMethodInvokeExpression cs2 = new CodeMethodInvokeExpression(); CodeMethodReferenceExpression cmr=new CodeMethodReferenceExpression(); cmr.MethodName="SayHell"; cs2.Method=cmr; Start.Statements.Add(new CodeExpressionStatement(cs2));
// 将方法加入到类型中 Hello.Members.Add( Start );
// 成员函数SayHello,有参数,无返回值
// public bool SayHello(string input) // { // Console.WriteLine(input); // return false; // } CodeMemberMethod cm = new CodeMemberMethod(); cm.Name = "SayHello"; cm.ReturnType=new CodeTypeReference(typeof(bool)); cm.Attributes = MemberAttributes.Public | MemberAttributes.Final|MemberAttributes.Static; cm.Parameters.Add( new CodeParameterDeclarationExpression( typeof(string),"input")); cm.Statements.Add( new CodeMethodInvokeExpression( new CodeSnippetExpression("Console"),"WriteLine", new CodeArgumentReferenceExpression("input"))); cm.Statements.Add(new CodeMethodReturnStatement( new CodePrimitiveExpression(false))); Hello.Members.Add(cm);
return CompileUnit; }
public static void GenerateCode(CodeDomProvider provider, CodeCompileUnit compileunit) { //获得生成代码的接口 ICodeGenerator gen = provider.CreateGenerator(); // 输出到文件 IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter("MyHello.cs", false), " "); // 使用代码生成接口产生源代码. gen.GenerateCodeFromCompileUnit(compileunit, tw, new CodeGeneratorOptions()); tw.Close(); }
public static CompilerResults CompileCode(CodeDomProvider provider, string filepath) { // 获得编译器. ICodeCompiler compiler = provider.CreateCompiler(); //配置编译参数。将SYSTEM。DLL引用进来,同时明确生成的代码为EXE CompilerParameters cp = new CompilerParameters(new string[] {"System.dll"}, filepath.Substring(0, filepath.LastIndexOf(".")+1)+"exe", false); cp.GenerateExecutable = true; // 调用编译器 CompilerResults cr = compiler.CompileAssemblyFromFile(cp, filepath); return cr; } }
} 上面的代码还有一点没实现。 
|