使用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 ...
随机推荐
- [jQuery]使用jQuery.Validate进行客户端验证(初级篇)
以前在做项目的时候就有个很大心病,就是微软的验证控件,虽然微软的验证控件可以帮我们完成大部分的验证,验证也很可靠上手也很容易,但是我就是觉得不爽,主要理由有以下几点: 1.拖控件太麻烦,这个是微软控件 ...
- javascript js获取url及url参数解析
js获取url及url参数解析 一.获取url: var url=window.location.herf; 二.url参数解析: function GetRequest() { var url = ...
- oracle 闪回区故障
之前为了验证rman,把数据库改为了归档备份,但闪回区却还是4G,结果自动备份在五一执行了,悲剧,幸好没出门.一顿乱搞,其实走了错误方向.思路: 提示untle free,将数据库闪回区先增加:alt ...
- uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型
在nesc的代码中,你会看到很多你不认识的数据类型,比如uint8_t等.咋一看,好像是个新的数据类型,不过C语言(nesc是C的扩展)里面好像没有这种数据类型啊!怎么又是u又是_t的?很多人有这样的 ...
- centOS系统将php升级到5.6 安装扩展
在文章中,我们将展示在centOS系统下如果将php升级到5.6,之前通过yum来安装lamp环境,直接升级的话,提示没有更新包,也就是说默认情况下php5.3.3是最新 1.查看已经安装的php版本 ...
- Frameset框架,在同一个浏览器窗口中显示不止一个页面
总结一下.通过使用Frameset框架,可以在同一个浏览器窗口中显示不止一个页面. 先举个例子: 1 <frameset rows="100,*" cols="*& ...
- jmeter-Http信息头管理器
今天遇到的问题是:一个报名接口,用户先要登录后,再去报名.而登录页面:用户名.密码.动态图形验证码,所以不能直接使用jmeter参数传值方法. 测试的时候,需要先登录,获取ticket后,才能去请求下 ...
- ArcGIS api for javascript-图层控制(图层树)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 【转】C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉
http://www.cnblogs.com/summer_adai/archive/2013/04/26/3045261.html
- mybatis和jdbc分析
从这个图上可以看出mybatis的整体执行图 jdbc的 mybatis对很多类型进行了转化,减少了开发的量