深入浅出.NET代码生成系列(7):动态生成代码与编译综合示例

来源:互联网 发布:怎么卸载mac上的office 编辑:程序博客网 时间:2024/05/22 11:50

前面说了这么多,大家可能会觉得,好像没弄出个玩意儿来啊,对啊,所以,本文就来个可以弄出个玩意儿的东东。

说明一下,这是一个综合示例,分为两大部分,第一部分,生成代码,输出到控制台窗口中;第二部分,把这些代码动态进行编译,并生成一个WinForm应用程序,双击动态编译的程序可以运行起来,点击窗口上的按钮,会弹出一个对话框。

好,下面我把整个示例的代码贴出来,很简单,你就新建一个控制台应用程序就可以了。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.CodeDom;using System.CodeDom.Compiler;namespace Example{    class Program    {        static void Main(string[] args)        {            CodeCompileUnit MyUnit = new CodeCompileUnit();            // 一个命名空间            CodeNamespace MyNamespace = new CodeNamespace("MyApp");            MyNamespace.Imports.Add(new CodeNamespaceImport("System"));            MyNamespace.Imports.Add(new CodeNamespaceImport("System.Windows.Forms"));            MyNamespace.Imports.Add(new CodeNamespaceImport("System.Drawing"));            MyNamespace.Imports.Add(new CodeNamespaceImport("System.Text"));            // 定义一个类            CodeTypeDeclaration MyClass = new CodeTypeDeclaration("MainForm");            MyClass.Attributes = MemberAttributes.Public;            MyClass.BaseTypes.Add(new CodeTypeReference("Form"));            CodeMemberField buttonField = new CodeMemberField("Button", "button1");            buttonField.InitExpression = new CodePrimitiveExpression(null);            MyClass.Members.Add(buttonField);            // 构造函数            CodeConstructor MyConstr = new CodeConstructor();            // 实例化Button类            MyConstr.Statements.Add(                new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"),                    new CodeObjectCreateExpression("Button", new CodeExpression[] { })));            // 为Button实例的相关属性赋值            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"), "Text"),                    new CodePrimitiveExpression("请点击这里")                ));            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"), "Width"),                    new CodePrimitiveExpression((int)285)                ));            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"), "Height"),                    new CodePrimitiveExpression((int)65)                ));            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"), "Location"),                    new CodeObjectCreateExpression("Point", new CodePrimitiveExpression((int)60), new CodePrimitiveExpression((int)80))                ));            // 绑定Button的Click事件            MyConstr.Statements.Add(new CodeAttachEventStatement(                    new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"), "Click",                    new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "button1_Click")                ));            // 设置窗口的宽度和高度            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(),"Width"),                    new CodePrimitiveExpression((int)450)                ));            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Height"),                    new CodePrimitiveExpression((int)300)                ));            // 设置窗口标题            MyConstr.Statements.Add(new CodeAssignStatement(                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Text"),                    new CodePrimitiveExpression("我的应用程序")                ));            // 将Button变量添加到Form的控件集合中            MyConstr.Statements.Add(new CodeExpressionStatement(                    new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(),"Controls"),                        "Add",                        new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "button1"))                ));            MyClass.Members.Add(MyConstr);            // 按钮单击处理程序            CodeMemberMethod MyHandlerMethod = new CodeMemberMethod();            MyHandlerMethod.Attributes = MemberAttributes.Private;            MyHandlerMethod.Name = "button1_Click";            MyHandlerMethod.Parameters.Add(new CodeParameterDeclarationExpression("Object", "sender"));            MyHandlerMethod.Parameters.Add(new CodeParameterDeclarationExpression("EventArgs", "e"));            // 方法中的描述            MyHandlerMethod.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(                    new CodeTypeReferenceExpression("MessageBox"),                    "Show",                    new CodePrimitiveExpression("你好啊,欢迎点击。"))                ));            // 将方法添加到类成员中            MyClass.Members.Add(MyHandlerMethod);            // 将类添加到命名空间            MyNamespace.Types.Add(MyClass);            // 将命名空间添加到编译单元            MyUnit.Namespaces.Add(MyNamespace);            // 入口点函数            CodeEntryPointMethod main = new CodeEntryPointMethod();            main.Statements.Add(new CodeExpressionStatement(                    new CodeMethodInvokeExpression(                            new CodeTypeReferenceExpression("Application"),                            "Run",                            new CodeObjectCreateExpression("MainForm", new CodeExpression[] { })                        )                ));            MyClass.Members.Add(main);            // 输出生成的代码            CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");            provider.GenerateCodeFromCompileUnit(MyUnit, Console.Out, new CodeGeneratorOptions { BracingStyle = "C" });                        // 编译程序集            CompilerParameters param = new CompilerParameters();            param.CompilerOptions = @"/t:winexe /out:Myapp.exe ";            param.IncludeDebugInformation = false;            param.ReferencedAssemblies.Add("mscorlib.dll");            param.ReferencedAssemblies.Add("System.Drawing.dll");            param.ReferencedAssemblies.Add("System.Windows.Forms.dll");            param.ReferencedAssemblies.Add("System.dll");            CompilerResults result = provider.CompileAssemblyFromDom(param, MyUnit);            if (result.Errors.Count!=0)            {                Console.WriteLine("\n------------------- 编译错误 -------------------------- ");                foreach (CompilerError err in result.Errors)                {                    Console.WriteLine("信息:{0}",err.ErrorText);                }            }            else            {                Console.WriteLine("编译成功。");            }            Console.ReadKey();        }    }}


运行程序,代码生成完成,并且成功编译,如下图所示。

 

那么,生成的WinForm程序在哪儿呢?上面代码中使用了 /out:Myapp.exe 参数,那么这个EXE在哪呢,相对路径,也就是和当前应用程序在同一个目录,现在,打开你的项目所在的位置,找到 \bin\Debug,看到那个Myapp.exe没?看到了就双击运行。好的,奇迹的一刻发生了。

 

怎么样?这回该有点玩意儿了吧?

总结一下,这个动态生成代码,说实话,平时用到它的机会不多,所以,我也没详细讲述,再者,用起来也不复杂,痛苦的是思路。所以,有人问,这个动态生成或动态编译在实际应用中有啥用处?呵呵,开玩笑地回答你:做木马!呵呵。

 

 

原创粉丝点击