利用Refly和CodeDom实现代码的动态生成和动态编译

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的工作机制应该还是足够的,同时也希望与大家探讨一下进一步的应用。

生成类代码的代码如下所示:

            #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 Reflynamespace 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实现代码的动态生成和动态编译,如需转载请自行联系原博主。

时间: 2024-08-02 12:32:37

利用Refly和CodeDom实现代码的动态生成和动态编译的相关文章

复杂表单的动态生成与动态验证

这里所谓的复杂表单,是指表单中包含多种不同的输入类型,比如下拉列表框.单行文本.多行文本.数值等.在经常需要更换这类表单的场合,需要有一个表单的动态生成程序.本文介绍的正是这样一个系统,它以数据库保存表单定义数据,利用ASP脚本动态生成表单HTML代码以及验证表单输入的脚本. 一.定义数据库表结构 在Web上经常可以看到"每周调查"之类的表单,这就是一种需要经常更新的表单.如果有一个动态生成表单及其验证脚本的程序,可以大大减少制作这些表单的工作量. 在本文的动态表单生成与验证示例中,我

复杂表单的动态生成与动态验证(转)

动态|动态验证 这里所谓的复杂表单,是指表单中包含多种不同的输入类型,比如下拉列表框.单行文本.多行文本.数值等.在经常需要更换这类表单的场合,需要有一个表单的动态生成程序.本文介绍的正是这样一个系统,它以数据库保存表单定义数据,利用ASP脚本动态生成表单HTML代码以及验证表单输入的脚本. 一.定义数据库表结构 在Web上经常可以看到"每周调查"之类的表单,这就是一种需要经常更新的表单.如果有一个动态生成表单及其验证脚本的程序,可以大大减少制作这些表单的工作量. 在本文的动态表单生成

jQuery操作动态生成的内容的方法_jquery

本文实例讲述了jQuery操作动态生成的内容的方法.分享给大家供大家参考,具体如下: 由于jQuery是页面一加载获取页面元素的,后期动态生成的元素,通过$("#xxxx")获取不到,需要用原始的js语句来获取: document.getElementById("xxx").value 对于动态生成的元素,bind绑定的事件 也无法触发,需要通过jQuery提供的另外一个方法 .live() 这个方法是基本是的 .bind() 方法的一个变体.使用 .bind()

php利用imagecreatetruecolor动态生成高清图片代码

//实例用我们用imagecreatetruecolor header ('Content-type: image/png'); $im = @imagecreatetruecolor(120, 20)       or die('Cannot Initialize new GD image stream'); $text_color = imagecolorallocate($im, 233, 14, 91); imagestring($im, 1, 5, 5,  'A Simple Text

使用xsl来动态生成java代码

动态 xsl本身就是一个构型良好的xml,它能够把一个xml文档转换成另外一个xml文档,或者转换成文本文件.html文件等等.这里就是利用xsl来动态的生成我们想要的java文件(从某种角度看,java代码其实也就是一个文本文件),希望能够通过这篇文章,看到xml以及相关的技术所具有的强大能力! 这里首先给一个xml例子,我们将通过一个xsl从该xml文件中抽取有用的信息来生成java代码(实际上是一个javabean): 以下内容为程序代码<?xml version="1.0"

利用OWC服务器端组件动态生成图表

动态|服务器|图表 利用OWC服务器端组件动态生成图表 以前在这里也曾经有一些文章谈到了在ASP中生成动态图表的问题,但那些文章中所谈到的一些方法都有某些方面的限制,如需要在客户端安装office2000或安装OWC,有些则可能在Intranet中使用时没什么问题,但在通过Internet访问的时候,就可能出现无法正常工作的现象(这主要和SQL Server的安全设置有关).那么,我们如何来避免这些问题呢?有一个很好的方法,就是将在ASP中生成的图表转换成图片文件保存在服务器上,这样用户最终看到

利用ASP.NET技术动态生成HTML页面

思路 1.利用如Dw-Mx这样的工具生成html格式的模板,在需要添加格式的地方加入特殊标记(如$htmlformat$),动态生成文件时利用代码读取此模板,然后获得前台输入的内容,添加到此模板的标记位置中,生成新文件名后写入磁盘,写入后再向数据库中写入相关数据. 2.使用后台代码硬编码Html文件,可以使用HtmlTextWriter类来写html文件. 优点 1.可以建立非常复杂的页面,利用包含js文件的方法,在js文件内加入document.write()方法可以在所有页面内加入如页面头,

利用ASP.NET技术动态生成HTML页面_ASP.NET

思路 1. 利用如Dw-Mx这样的工具生成html格式的模板,在需要添加格式的地方加入特殊标记(如$htmlformat$),动态生成文件时利用代码读取此模板,然后获得前台输入的内容,添加到此模板的标记位置中,生成新文件名后写入磁盘,写入后再向数据库中写入相关数据. 2. 使用后台代码硬编码Html文件,可以使用HtmlTextWriter类来写html文件. 优点 1. 可以建立非常复杂的页面,利用包含js文件的方法,在js文件内加入document.write()方法可以在所有页面内加入如页

ASP动态生成的javascript表单验证代码

javascript|表单验证|动态 以网上down了一个ASP动态生成Form验证javascript的代码,自己扩容了一下.作者的大名我给忘了,不过我记得清楚,从第一条至第九条的代码都是该作者的原创.至于九至第十五条却是本人自己加的哦.而且由于本人水平有限,从第九条至第十五条不见得会条条生效啊?呵呵,其实把它贴在这里没有什么必要的,因为这点小会伎俩谁都会用的,我把它的作用定位为:开发时找不到该函数时到这里拷贝一下就可以了.呵,因为我即没有刻录机也没有移动硬盘.实在是没有办法把这些代码随身携带