zoukankan      html  css  js  c++  java
  • CodeDom系列开篇HelloWord

    最近在自己实践一个异常扑捉设计,在模块中我觉得该给用户提供的是代码生成工具,而不是怎么去做,再自己去写代码。现在代码模板生成的有很多

    但我选择了用微软的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:生成的代码:
    image

    2:运行结果:

    image 

    上面代码很简单,我特意也把注释写上了,所以不用一句一句的讲解了,哈哈。

    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--破狼

  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/whitewolf/p/1760708.html
Copyright © 2011-2022 走看看