代码改变世界

使用CompilerResults 方法动态的编译类

2013-04-01 10:40  随风浪迹天涯  阅读(1745)  评论(0编辑  收藏  举报

-------------------今天愚人节,祝ITer 愚人节快乐----------------------

好吧,我out了,我是第一次使用这个类。觉得比较新奇,所以就整出来,大家共享贡献。

需要实现这个demo,你需要导入以下三个命名空间:

using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

第一部分:CompileClass

在这个方法中,我们放了自己hard code 在运行需要动态编译的类的方法体,当然在现实项目中,我们可以传自己需要处理的类即可。我在这个类里面创建了一string类型的name和一个int类型的age。

代码如下:

public Assembly CompileClass()
{
    string code = @"
         public class Test
         {
            public string name{get; set;} 
            
            public int age{get; set;}

         }";

    CompilerResults compilerResults = CompileScript(code);//调用CompileScript 方法。

    if (compilerResults.Errors.HasErrors)
    {
        throw new InvalidOperationException("Expression has a syntax error.");
    }

    Assembly assembly = compilerResults.CompiledAssembly;//得到程序集对象。里面包含了类、接口、方法、属性。。。等等。

    return assembly;
}

对上面的代码没有多少难度,需要注意的是,我们写些了一个方法-----CompilerScript,主要是根据传进来的类 字符串,生成CompilerResult为返回类型的结果。

第二部分:CompilerScript

代码如下:

public  CompilerResults CompileScript(string source)
{
    CompilerParameters parms = new CompilerParameters();

    parms.GenerateExecutable = false;// 是否生成exe 可执行文件。
    parms.GenerateInMemory = true;//是否在内存中生成space
    parms.IncludeDebugInformation = false;//是否包含debug 信息

    CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");

    return compiler.CompileAssemblyFromSource(parms, source);
}

对CodeDomProvider 类而言,它是一个有关动态编译的类。可以查看博客园的专题报告CodeDom 。这里有很详细的解释,其实我也正在学习中呢。见笑了。

好的,接着我们开始试验:

static void Main(string[] args)
        {
            Server s = new Server();//实例化本类
            Assembly ass = s.ComileClass();  //得到程序集

            List<Object> df = new List<object>();// 定义一个object的List对象

            Dictionary<string, int> tst1 = new Dictionary<string, int>();
            tst1.Add("任贤齐", 23);
            tst1.Add("刘德华", 24);
            tst1.Add("关之琳", 25);

            foreach (KeyValuePair<string, int> d in tst1)
            {
                object obj = ass.CreateInstance("student");//实例化student类
                obj.GetType().GetProperty("name").SetValue(obj, d.Key, null);//对上面实例化的类的name进行设置
                obj.GetType().GetProperty("age").SetValue(obj, d.Value, null);//对上面实例化的类age进行设置值

                df.Add(obj);//装进List的集合中。
            }

        // 开始列出所有的结果。。。
foreach (object o in df) { Console.WriteLine(o.GetType().GetProperty("name").GetValue(o, null).ToString()); Console.WriteLine(o.GetType().GetProperty("age").GetValue(o, null).ToString()); } }

得到的结果如下:

结束,谢谢大家。