zoukankan      html  css  js  c++  java
  • 利用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 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);
    }
    }
    }



    主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
    专注于Winform开发框架/混合式开发框架Web开发框架Bootstrap开发框架微信门户开发框架的研究及应用
      转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com 
        
  • 相关阅读:
    luogu P1833 樱花 看成混合背包
    luogu P1077 摆花 基础记数dp
    luogu P1095 守望者的逃离 经典dp
    Even Subset Sum Problem CodeForces
    Maximum White Subtree CodeForces
    Sleeping Schedule CodeForces
    Bombs CodeForces
    病毒侵袭持续中 HDU
    病毒侵袭 HDU
    Educational Codeforces Round 35 (Rated for Div. 2)
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/2426091.html
Copyright © 2011-2022 走看看