利用Refly和CodeDom实现代码的动态生成和动态编译
2012-03-30 21:52
726 查看
CodeDom是.NET框架中比较强大也是比较难懂的对象模型,通过它可以实现.NET支持各种语言代码的动态生成及动态编译。我们先来看看CodeDom的定义:.NET Framework 中包含一个名为“代码文档对象模型”(CodeDOM) 的机制,该机制使编写源代码的程序的开发人员可以在运行时,根据表示所呈现代码的单一模型,用多种编程语言生成源代码。
Refly则是国外一个开发者对CodeDom进行封装,目的是使得Codedom的实现更加方便易懂,和CodeDom的使用对比,代码更加简洁优雅,不过要了解整体的东西,也需要对CodeDOM进行详细的了解才能熟练应用。
本人在研究学习Refly当中(详细可以参考http://www.codeproject.com/Articles/6283/Refly-makes-the-CodeDom-er-life-easier),对其中简单的应用有一些体会,做了一个使用Refly生成代码的例子进行测试,并使用CodeDOM进行动态编译。例子应该还算简单,用来说明Refly的工作机制应该还是足够的,同时也希望与大家探讨一下进一步的应用。
生成类代码的代码如下所示:
编译代码好像Refly没有找到,所以用原始的CodeDOM的对象操作进行代码的动态编译,编译代码如下所示:
代码编译了,我们使用的编译好的类也就可以了,使用操作代码如下所示,例子我使用反射,把生成的对象加载,并绑定到PropertyGrid控件中。
最终例子运行的效果如下所示。
其实最终生成的User类代码如下所示。
Refly则是国外一个开发者对CodeDom进行封装,目的是使得Codedom的实现更加方便易懂,和CodeDom的使用对比,代码更加简洁优雅,不过要了解整体的东西,也需要对CodeDOM进行详细的了解才能熟练应用。
本人在研究学习Refly当中(详细可以参考http://www.codeproject.com/Articles/6283/Refly-makes-the-CodeDom-er-life-easier),对其中简单的应用有一些体会,做了一个使用Refly生成代码的例子进行测试,并使用CodeDOM进行动态编译。例子应该还算简单,用来说明Refly的工作机制应该还是足够的,同时也希望与大家探讨一下进一步的应用。
生成类代码的代码如下所示:
#region 生成代码 //创建命名空间 NamespaceDeclaration ns = new NamespaceDeclaration("Demo"); ns.Imports.Add("System.Xml"); ns.Imports.Add("System.IO"); ns.Imports.Add("System.ComponentModel"); ns.Imports.Add("System.Xml.Serialization"); // 创建类定义 ClassDeclaration user = ns.AddClass("User"); //添加类说明 user.Doc.Summary.AddText("测试用户类描述"); user.Doc.Remarks.Add("para"); user.Doc.Remarks.Into(); user.Doc.Remarks.AddText("该类是使用Refly进行生成"); user.Doc.Remarks.OutOf(); // 添加字段 FieldDeclaration name = user.AddField(typeof(string), "name"); FieldDeclaration age = user.AddField(typeof(int), "age"); // 添加构造函数(默认) user.AddConstructor(); ConstructorDeclaration cstr = user.AddConstructor(); // 添加构造函数(参数) ParameterDeclaration cstr_name = cstr.Signature.Parameters.Add(typeof(string), "name", true); cstr.Body.AddAssign(Expr.This.Field(name), Expr.Arg(cstr_name)); // 添加属性Name PropertyDeclaration proName = user.AddProperty(name, true, true, false); proName.Doc.Summary.AddText("用户名称"); //添加属性的Attribute AttributeDeclaration attr = proName.CustomAttributes.Add(typeof(XmlElementAttribute)); attr.Arguments.Add("ElementName", Expr.Prim(proName.Name)); // 添加属性Age PropertyDeclaration proAge = user.AddProperty(age, true, true, false); proName.Doc.Summary.AddText("用户年龄"); //添加方法 MethodDeclaration add = user.AddMethod("Add"); add.Doc.Summary.AddText("添加用户内容"); ParameterDeclaration pName = add.Signature.Parameters.Add(typeof(string), "name", true); add.Doc.AddParam(pName); ParameterDeclaration pAge = add.Signature.Parameters.Add(typeof(int), "age", true); add.Body.Add(Stm.Assign(Expr.This.Prop("Name"), Expr.Arg(pName))); add.Body.Add(Stm.Assign(Expr.This.Prop("Age"), Expr.Arg(pAge))); //添加方法2 MethodDeclaration show = user.AddMethod("Show"); show.Doc.Summary.AddText("输出用户名称"); show.Body.Add(Expr.Snippet("Console").Method("WriteLine").Invoke(Expr.This.Prop("Name"))); // 输出结果 Refly.CodeDom.CodeGenerator gen = new Refly.CodeDom.CodeGenerator(); gen.Provider = Refly.CodeDom.CodeGenerator.CsProvider; gen.GenerateCode(Application.StartupPath + "/CS", ns); #endregion
编译代码好像Refly没有找到,所以用原始的CodeDOM的对象操作进行代码的动态编译,编译代码如下所示:
#region 动态编译代码 string file = string.Format("{0}\\CS\\Demo\\User.cs", Application.StartupPath); string code = FileUtil.FileToString(file); string output = string.Format("{0}\\CS\\Demo\\User.dll", Application.StartupPath); CSharpCodeProvider codeProvider = new CSharpCodeProvider(); CompilerParameters parameters = new CompilerParameters(); parameters.ReferencedAssemblies.Add("System.dll"); parameters.ReferencedAssemblies.Add("System.Data.dll"); parameters.ReferencedAssemblies.Add("System.Xml.dll"); parameters.GenerateInMemory = false; parameters.TreatWarningsAsErrors = false; parameters.OutputAssembly = output; //设定输出文件名称路径 //判断编译结果 //CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code); CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, file); if (results.Errors.HasErrors) { string errorMessage = ""; errorMessage = results.Errors.Count.ToString() + " Errors:"; for (int x = 0; x < results.Errors.Count; x++) { errorMessage = errorMessage + "\r\nLine: " + results.Errors[x].Line.ToString() + " - " + results.Errors[x].ErrorText; } MessageUtil.ShowError(errorMessage); } //string path = results.PathToAssembly; return results.Errors.Count == 0; #endregion
代码编译了,我们使用的编译好的类也就可以了,使用操作代码如下所示,例子我使用反射,把生成的对象加载,并绑定到PropertyGrid控件中。
private void btnTest_Click(object sender, EventArgs e) { GenerateCompile(); string assemblyFile = string.Format("{0}\\CS\\Demo\\User.dll", Application.StartupPath); if (File.Exists(assemblyFile)) { Assembly assObj = Assembly.LoadFile(assemblyFile); if (assObj != null) { object obj = assObj.CreateInstance("Demo.User"); this.propertyGrid1.SelectedObject = obj; } } }
最终例子运行的效果如下所示。
其实最终生成的User类代码如下所示。
// Generated by Refly namespace Demo { using System; using System.Xml; using System.IO; using System.ComponentModel; using System.Xml.Serialization; /// <summary>测试用户类描述</summary> /// <remarks> ///<para>该类是使用Refly进行生成</para> /// </remarks> public class User { private int _age; private string _name; public User() { } public User(string name) { this._name = name; } /// <summary>用户名称用户年龄</summary> [XmlElementAttribute(ElementName="Name")] public virtual string Name { get { return this._name; } set { this._name = value; } } public virtual int Age { get { return this._age; } set { this._age = value; } } /// <summary>添加用户内容</summary> /// <param name="name" /> public virtual void Add(string name, int age) { this.Name = name; this.Age = age; } /// <summary>输出用户名称</summary> public virtual void Show() { Console.WriteLine(this.Name); } } }
相关文章推荐
- 利用Refly和CodeDom实现代码的动态生成和动态编译
- 使用CodeDOM实现代码生成及动态编译
- 使用CODEDOM动态实现代码的生成,编译
- 使用CODEDOM动态实现代码的生成,编译
- 利用VS编译生成事件实现代码及时提交到Git
- js+插件实现代码复制及动态生成二维码扫描、分享到朋友圈QQ空间功能
- C#利用定时任务插件实现在后台线程中批量把动态文件生成静态文件方法
- 动态生成与编译(七)----根据CodeDOM生成源代码
- 深入浅出.NET代码生成系列(7):动态生成代码与编译综合示例
- 利用Django中的url方法实现地址动态拼接自动生成超链接地址
- 微信小程序动态生成二维码的实现代码
- 浅谈Visual Studio动态代码生成的实现基础
- 利用Ext Js生成动态树实例代码
- 利用js实现前台动态添加文本框,后台获取文本框内容(示例代码)
- 利用PHP为大图片生成缩略图代码实现
- CodeDom自动生成代码并编译
- 利用动态创建层技术实现无冗余代码为表单自动添加错误提示
- 利用CodeDom和反射动态编译并执行程序集