原文地址: 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
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?