C#代码生成类

原文地址: System.CodeDom详述及其应用实例

这里简单搬运代码然后在Unity打印出了C#的生成代码,再记录一个简单的初步认识,学这个是想用一下自动生成代码这个功能。

原文代码有些地方是有点错误的,改了之后才能整合运行

利用CodeDom可以生成编程语言代码,
假设我现在有个用CodeDom指定C#生成某个功能类的代码的脚本
只需更改指定的语言参数,其他的部分都不用变更,就能做出其他语言的相同功能的类。

创建C#代码

生成的代码结果

在这里插入图片描述

public CodeDomProvider()
    {
        currentNameSpace = GenerateClassUtil.InitializeNameSpace("TestSpace");
        CodeTypeDeclaration ctd = GenerateClassUtil.CreateClass ("HelloWorld");
        // 把类加入到名称空间
        currentNameSpace.Types.Add (ctd);
        CodeEntryPointMethod mtd = GenerateClassUtil.CreateMethod();
        
        // 把方法加入到类
        ctd.Members.Add (mtd);
        
        //变量声明
        CodeVariableDeclarationStatement VariableDeclaration =
            GenerateClassUtil.DeclareVariables (typeof (StringBuilder), "sbMessage");
        
        // 把变量声明加入到方法
        mtd.Statements.Add (VariableDeclaration);
        
        //声明数组
        CodeVariableDeclarationStatement array = GenerateClassUtil.InitializeArray
        ("Characters", 'H', 'E', 'L', 'L', 'O', ' ',
            'W', 'O', 'R', 'L', 'D');
        
        // 把数组加入到方法
        mtd.Statements.Add (array);
        
        //声明循环
        CodeIterationStatement loop = GenerateClassUtil.CreateLoop("intCharacterIndex");
        
        // 把循环加入到方法
        mtd.Statements.Add (loop);
        
        // 数组索引
        CodeArrayIndexerExpression index = GenerateClassUtil.CreateArrayIndex("Characters",
            "intCharacterIndex");
        
        // 加入一个语句,它将调用sbMessage对象的“Append”方法
        loop.Statements.Add (new CodeMethodInvokeExpression (
            new CodeSnippetExpression ("sbMessage"),"Append",
            index));
        
        // 循环结束后,输出所有字符追加到sbMessage对象
        
        
        // 后得到的结果
        mtd.Statements.Add (new CodeSnippetExpression
            ("Console.WriteLine (sbMessage.ToString())"));

        
        
       Debug.Log(GenerateCode(GenerateClassUtil.CSharpCode));  
    } 

生成最终代码

据目前了解,CodeDom生成代码是以命名空间来生成的,生成的时候传入命名空间,定义在该空间下的代码就生成了。


  public static ICodeGenerator CSharpCode
    {
        get
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();
            ICodeGenerator codeGen = provider.CreateGenerator ();
            return (codeGen);
        }
  
    } 

 private string GenerateCode (ICodeGenerator CodeGenerator)
    {
        // CodeGeneratorOptions允许我们指定各种供代码生成器
        // 使用的格式化选项
        CodeGeneratorOptions cop = new CodeGeneratorOptions();
        // 指定格式:花括号的位置
        cop.BracingStyle = "C";
        // 指定格式:代码块的缩进方式
        cop.IndentString = " ";
        
        // GenerateCodeFromNamespace要求传入一个TextWriter以
        // 容纳即将生成的代码。这个TextWriter可以是一个StreamWriter、
        // 一个StringWriter或一个IndentedTextWriter。
        // StreamWriter可用来将代码输出到文件。
        // StringWriter可绑定到StringBuilder,后者可作为一个变量引用。
        // 在这里,我们把一个StringWriter绑定到StringBuilder sbCode。
        StringBuilder sbCode = new StringBuilder();
        StringWriter sw = new StringWriter(sbCode);
  
        // 生成代码!
        CodeGenerator.GenerateCodeFromNamespace(currentNameSpace, sw,cop);
        
        return sbCode.ToString();
    } 

GenerateCode(GenerateClassUtil.CSharpCode)

生成命名空间

public  static  CodeNamespace InitializeNameSpace(string Name)
    {
        // 初始化CodeNameSpace变量,指定名称空间的名称
        CodeNamespace CurrentNameSpace = new CodeNamespace (Name);
        // 将一些名称空间加入到要导入的名称空间集合。
        // 各种语言如何导入名称空间的细节由每种语言对应
        // 的CodeProvider分别处理。
        CurrentNameSpace.Imports.Add (new CodeNamespaceImport("System"));
        CurrentNameSpace.Imports.Add (new CodeNamespaceImport("System.Text"));
        return CurrentNameSpace;
    }

生成类

  public  static CodeTypeDeclaration CreateClass (string Name)
    {
        // 新建一个CodeTypeDeclaration对象,指定要创建的类的名称
        CodeTypeDeclaration ctd = new CodeTypeDeclaration (Name);
        // 指定这个CodeType是一个类,而不是一个枚举变量或struct
        ctd.IsClass = true;
        // 这个类的访问类型是public
        ctd.Attributes = MemberAttributes.Public;
        // 返回新创建的类
        return ctd;
    }

生成方法

  public  static CodeEntryPointMethod CreateMethod()
    {
        // 创建一个方法
        CodeEntryPointMethod method = new CodeEntryPointMethod();
        // 指定该方法的修饰符:public,static
        method.Attributes = MemberAttributes.Public |
                            MemberAttributes.Static;
        // 返回新创建的方法
        return method;
    } 

声明变量

 public  static   CodeVariableDeclarationStatement
        DeclareVariables(System.Type DataType,
            string Name)
    {
        // 为将要创建的变量类型创建一个CodeTypeReference对象,
        // 这使得我们不必去关注该类数据在特定语言环境中的
        // 与数据类型有关的细节问题。
        CodeTypeReference tr = new CodeTypeReference (DataType );
        // CodeVariableDeclarationStatement对象使得我们不必纠缠于
        // 与特定语言有关的下列细节:在该语言的变量声明语句中,
        // 应该是数据类型在前,还是变量名称在前;声明变量时是
        // 否要用到Dim之类的关键词.
        CodeVariableDeclarationStatement Declaration =
            new CodeVariableDeclarationStatement(tr, Name);
        // CodeObjectCreateExpression负责处理所有调用构造器的细节。
        // 大多数情况下应该是new,但有时要使用New。但不管怎样,
        // 我们不必去关注这些由语言类型决定的细节.
        CodeObjectCreateExpression newStatement = new
            CodeObjectCreateExpression ();
        // 指定我们要调用其构造器的对象.
        newStatement.CreateType = tr;
        // 变量将通过调用其构造器的方式初始化.
        Declaration.InitExpression = newStatement;
        return Declaration;
    } 
    

创建循环

public  static  CodeIterationStatement CreateLoop(string LoopControlVariableName)
    {
        // 声明一个新的变量,该变量将作为
        // 循环控制变量
        CodeVariableDeclarationStatement Declaration;
        // 声明一个管理所有循环逻辑的CodeIterationStatement
        CodeIterationStatement forloop = new CodeIterationStatement();
        // 为动态声明的变量指定数据类型的另一种方法:
        // 用typeof函数获得该数据类型的Type对象,不必
        // 用到该类数据的变量
        Declaration = new CodeVariableDeclarationStatement(typeof (int),
            LoopControlVariableName);
        // 指定一个简单的初始化表达式:
        // 将新变量设置为0
        Declaration.InitExpression = new CodeSnippetExpression ("0");
        // 这个新声明的变量将用来初始化循环
        forloop.InitStatement = Declaration;
        // CodeAssignStatement用来处理赋值语句。
        // 这里使用的构造器要求提供两个表达式,第一个位于
        // 赋值语句的左边,第二个位于赋值语句的右边。
        // 另一种办法是:调用默认的构造器,然后分别显式设置
        // 左、右两个表达式。
        CodeAssignStatement assignment = new CodeAssignStatement(
            new CodeVariableReferenceExpression(LoopControlVariableName),
            new CodeSnippetExpression (LoopControlVariableName + " + 1" ));
        // 在循环迭代中使用赋值语句。
        forloop.IncrementStatement = assignment;
        // 当循环控制变量超出数组中的字符个数时,
        // 循环结束
        forloop.TestExpression = new CodeSnippetExpression
            (LoopControlVariableName + " < Characters.Length");
        return forloop;
    } 
    

初始化数组

public  static CodeVariableDeclarationStatement InitializeArray (string Name,
        params char[] Characters )
    {
        // 从参数中传入的字符数组获得一个CodeTypeReference 对象,
        // 以便在生成的代码中复制该数据类型.
        CodeTypeReference tr = new CodeTypeReference (Characters.GetType());
        // 声明一个匹配原始数组的数组
        CodeVariableDeclarationStatement Declaration =
            new CodeVariableDeclarationStatement (tr, Name);
        // CodePrimitiveExpression代表“基本”或值数据类型,
        // 例如char、int、double等等。
        // 我们将用这类基本数据类型构成的一个数组来
        // 初始化我们正在声明的数组。
        CodePrimitiveExpression[] cpe = new
            CodePrimitiveExpression[Characters.Length];
        // 循环遍历原始字符数组,
        // 为CodePrimitiveExpression类型的数组创建对象。
        
        
        
        for (int i = 0; i < Characters.Length ; i++)
        {
            // 每一个CodePrimitiveExpression将有一个字符的语言
            // 中立的表示。
            cpe[i] = new CodePrimitiveExpression (Characters[i]);
        }
        // CodeArrayCreateExpression负责调用数组中数据类型的
        // 默认构造器。
        // 由于我们还传入了一个CodePrimitiveExpression的数组,
        // 所以不必指定数组的大小,且数组中的每一个元素都将有
        // 合适的初值。
        CodeArrayCreateExpression array = new
            CodeArrayCreateExpression(tr, cpe);
        // 指定:该CodeArrayCreateExpression将初始化数组变量声明。
        Declaration.InitExpression = array;
        return Declaration;
    }
    

创建数组索引

 public  static   CodeArrayIndexerExpression CreateArrayIndex(string ArrayName, string IndexValue )
    {
        // 新建一个CodeArrayIndexerExpression
        CodeArrayIndexerExpression index = new CodeArrayIndexerExpression ();
        // Indices属性是一个能够支持多维数组的集合。不过这里我们只需要
        // 一个简单的一维数组。
        index.Indices.Add ( new CodeVariableReferenceExpression (IndexValue));
        // TargetObject指定了要索引的数组的名称。
        index.TargetObject = new CodeSnippetExpression (ArrayName);
        return index;
    } 
    

工程链接

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值