使用codedom自动生成代码
刚刚接触自动代码生成,便小试牛刀,解决了项目中的一些问题。
问题:我们的项目分成很多层次,当增加一个方法的时候,会显得异常繁琐,但每个层次之间的调用大同小异,所以尝试使用代码生成。现在假设有Engine, EngineBase,LocalEngine, RemoteEngine,Host等几个类,其定义和关系如下:
public class EngineFacade
{
private EngineBase engine = null;
public EngineFacade(bool isLocalEngine = true)
{
if (isLocalEngine)
{
engine = new LocalEngine();
}
else
{
engine = new RemoteEngine();
}
} public bool GetCurrentStatus()
{
return true;
}
} public abstract class EngineBase
{
public abstract bool GetCurrentStatus();
} public class LocalEngine : EngineBase
{
public override bool GetCurrentStatus()
{
return true;
}
} public class RemoteEngine : EngineBase
{
private IHost host = null; public RemoteEngine()
{
host = new Host();
} public override bool GetCurrentStatus()
{
return host.GetCurerntStatus();
}
} public interface IHost
{
bool GetCurerntStatus();
} public class Host : IHost
{
public bool GetCurerntStatus()
{
return true;
}
}
层次关系定义
上诉定义的类会被SampleClient调用:
public class SampleClient
{
public void Test()
{
var engine = new EngineFacade(false);
Console.WriteLine(engine.GetCurrentStatus());
}
}
SampleClient
如果我们需要增加一个新的方法SetStatus,如何避免额外的体力劳动呢?
解决方案:使用CodeDom进行动态代码生成。
class CodeGenerator
{
private CodeCompileUnit targetUnit = new CodeCompileUnit();
private CodeTypeDeclaration targetClass = new CodeTypeDeclaration("Test");
private static readonly string targetInstance = "engineInstance"; public CodeGenerator()
{
CodeNamespace sample = new CodeNamespace("CodeDomTest");
sample.Imports.Add(new CodeNamespaceImport("System"));
targetClass.IsClass = true;
targetClass.TypeAttributes = TypeAttributes.Public;
sample.Types.Add(targetClass);
targetUnit.Namespaces.Add(sample);
} public void AddMethod(string name, Type returnType, string comments, CodeExpression codeExpression)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
method.Name = name;
method.ReturnType = new CodeTypeReference(returnType);
method.Comments.Add(new CodeCommentStatement(comments));
CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement();
returnStatement.Expression = codeExpression;
method.Statements.Add(returnStatement);
targetClass.Members.Add(method);
} public void AddMethod(string name, Type returnType, string comments, CodeExpression codeExpression, string paraName, Type paraType)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
method.Name = name;
method.ReturnType = new CodeTypeReference(returnType);
method.Comments.Add(new CodeCommentStatement(comments));
method.Parameters.Add(new CodeParameterDeclarationExpression(paraType, paraName));
CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement();
returnStatement.Expression = codeExpression;
method.Statements.Add(returnStatement);
targetClass.Members.Add(method);
} public void AddMethod(string name, Type returnType, string comments, CodeExpression codeExpression, List<CodeParameterDeclarationExpression> parameters)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
method.Name = name;
method.ReturnType = new CodeTypeReference(returnType);
method.Comments.Add(new CodeCommentStatement(comments));
method.Parameters.AddRange(parameters.ToArray());
CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement();
returnStatement.Expression = codeExpression;
method.Statements.Add(returnStatement);
targetClass.Members.Add(method);
} public void AddAbstractMethod(string name, Type returnType, string comments)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
method.Name = name;
method.ReturnType = new CodeTypeReference(returnType);
method.Comments.Add(new CodeCommentStatement(comments));
targetClass.Members.Add(method);
} public void AddAbstractMethod(string name, Type returnType, string comments, string paraName, Type paraType)
{
CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
method.Name = name;
method.ReturnType = new CodeTypeReference(returnType);
method.Parameters.Add(new CodeParameterDeclarationExpression(paraType, paraName));
method.Comments.Add(new CodeCommentStatement(comments));
targetClass.Members.Add(method);
} public void AddField(string name, Type fieldType)
{
CodeMemberField member = new CodeMemberField();
member.Attributes = MemberAttributes.Private;
member.Name = name;
member.Type = new CodeTypeReference(fieldType);
targetClass.Members.Add(member);
} public void GenerateCode()
{
CodeDomProvider provider = new CSharpCodeProvider();
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
using (StreamWriter streamWriter = new StreamWriter("SampleReactorCode.cs"))
{
provider.GenerateCodeFromCompileUnit(targetUnit, streamWriter, options);
}
} public static void Start()
{
CodeGenerator sample = new CodeGenerator();
Test(sample);
sample.GenerateCode();
} private static void Test(CodeGenerator sample)
{
var methodToAdd = "Test";
var returnType = typeof(Dictionary<string, object>);
var paraname = "key";
var paraType = typeof(string);
var parTypes = new Dictionary<string, Type>() { { "no", typeof(int) }, { paraname, paraType } }; var parameters = GenerateParameters(parTypes);
var parArguments = GenerateParametersArguments(parTypes).ToArray(); sample.AddMethod(methodToAdd, returnType, "This is for engine facade",
new CodeMethodInvokeExpression(
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), targetInstance),
methodToAdd, parArguments), parameters);
sample.AddAbstractMethod(methodToAdd, returnType, "This is for engine base", paraname, paraType);
sample.AddMethod(methodToAdd, returnType, "This is for local engine",
new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "scenario"),
methodToAdd, parArguments), parameters);
sample.AddMethod(methodToAdd, returnType, "This is for remote engine",
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression(new CodeTypeReference("HostProxy")), methodToAdd,
parArguments), parameters); var dump = parArguments.ToList();
parameters.Insert(, new CodeParameterDeclarationExpression(typeof(string), "engineKey"));
dump.Insert(, new CodeArgumentReferenceExpression("engineKey"));
parArguments = dump.ToArray(); sample.AddMethod(methodToAdd, returnType, "This is for host",
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("InstanceManager"), methodToAdd, parArguments),
parameters); dump.Insert(, new CodePrimitiveExpression(methodToAdd));
dump.Insert(, new CodeArgumentReferenceExpression("host_name"));
parArguments = dump.ToArray();
sample.AddMethod(methodToAdd, returnType, "This is for host",
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("host"), string.Format("Invoke<{0}>", returnType.ToString())
, parArguments), parameters);
} private static List<CodeParameterDeclarationExpression> GenerateParameters(Dictionary<string, Type> parameterTypes)
{
return parameterTypes.Select(parameterType => new CodeParameterDeclarationExpression(parameterType.Value, parameterType.Key)).ToList();
}
private static List<CodeExpression> GenerateParametersArguments(Dictionary<string, Type> parameterTypes)
{
return parameterTypes.Select(parameterType => (CodeExpression)new CodeArgumentReferenceExpression(parameterType.Key)).ToList();
}
}
CodeGenerator
如何使用CodeDom,请参考动态源代码生成和编译。
使用codedom自动生成代码的更多相关文章
- mybatis generator maven插件自动生成代码
如果你正为无聊Dao代码的编写感到苦恼,如果你正为怕一个单词拼错导致Dao操作失败而感到苦恼,那么就可以考虑一些Mybatis generator这个差价,它会帮我们自动生成代码,类似于Hiberna ...
- java如何在eclipse编译时自动生成代码
用eclipse写java代码,自动编译时,如何能够触发一个动作,这个动作是生成本项目的代码,并且编译完成后,自动生成的代码也编译好了, java编辑器中就可以做到对新生成的代码的自动提示? 不生成代 ...
- MyBatis自动生成代码示例
在项目中使用到mybatis时,都会选择自动生成实体类,Mapper,SqlMap这三个东东. 手头上在用的又不方便,找了下网上,其实有很多文章,但有些引用外部文件时不成功,也不方便,所以重新整理了下 ...
- MyBatis使用Generator自动生成代码
MyBatis中,可以使用Generator自动生成代码,包括DAO层. MODEL层 .MAPPING SQL映射文件. 第一步: 配置好自动生成代码所需的XML配置文件,例如(generator. ...
- mybatis 自动生成代码(mybatis generator)
pom.xml 文件配置 引入 mybatis generator <properties> <mysql.connector.version>5.1.44</mysql ...
- ButterKnife的使用以及不能自动生成代码问题的解决
ButterKnife的使用以及不能自动生成代码问题的解决 转载请注明出处:http://www.cnblogs.com/zhengjunfei/p/5910497.html 最近换了个工作刚入职,又 ...
- 【MyBatis】MyBatis自动生成代码查询之爬坑记
前言 项目使用SSM框架搭建Web后台服务,前台后使用restful api,后台使用MyBatisGenerator自动生成代码,在前台使用关键字进行查询时,遇到了一些很宝贵的坑,现记录如下.为展示 ...
- mybatis-generator : 自动生成代码
[参考文章]:mybatis generator自动生成代码时 只生成了insert 而没有其他 [参考文章]:Mybatis Generator最完整配置详解 1. pom <plugin&g ...
- mybatis-generator自动生成代码插件
mybatis自动生成代码(实体类.Dao接口等)是很成熟的了,就是使用mybatis-generator插件. 它是一个开源的插件,使用maven构建最好,可以很方便的执行 插件官方简介: http ...
随机推荐
- python(一):作用域
与c相比,python作用域很奇特. 在Python中变量的作用域是由它在源代码中的位置决定的,这一点与c相似. python只支持4种作用域,即局部作用域,全局作用域,内置作用域,嵌套作用域. 比较 ...
- C# 顺序表---增删改查--逆至--删除最小值
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- java 文件的读写操作
java 文件的读写操作 一.读: public String getSetting() { HttpServletRequest request=org.apache.struts2.Servle ...
- Go语言环境安装-Mac
1.环境安装 Go SDK下载和安装,下载地址为:https://golang.org/dl/ Visual Studio Code下载和安装,下载地址为:https://code.visualstu ...
- iOS工程师 - 简历
基本信息 姓 名:张学友 性 别:男 年 龄:28 学 历:本科 毕业学校:广西师范大学 专 业:通信工程 手 ...
- CSS再学
css的注释 /*.......*/ 直接在html代码中写css <p style="color: rebeccapurple;font-size: 18px">Ha ...
- shell控制流程
#!/bin/bash #存储为a.sh == ] then #参数正确,返回0 else #参数错误,返回1 fi #!/bin/bash #存储为b.sh echo $? $ . ./a.sh $ ...
- vue学习二:
vue的常用标签: 1.<router-link to=''>主要实现跳转链接功能,属性to='/'即是跳转到path为'/'的路径. 2.v-bind动态绑定指令,格式为:v-bind: ...
- Eclipse导入GitHub项目两处报错处理
1.项目出现Could not calculate build plan:pligin 错误解决办法: 删除本地.m2仓库中 org.apache.maven.plugins:maven-resour ...
- sql 日期对比
来自这里