既然要使用动态编译,那么为他封装一个调用类,在调用时省去大量不必要的编码操作还是很有必要的。

  • 为什么要封装?

其实这个说起来很简单,就是发现现有的动态编译类在使用过程中显得并不是那么好用。我觉得我可以让他变的更易使用。

所以我应该重新封装了一个DynamicCompile类。

不过在这之前我还要考虑一下一个问题:

  • 我需要什么?

在使用动态编译的过程中,我逐渐的发现,动态编译有以下几种情况

1.我拼接了一个静态类的代码,需要返回这个类的类型

2.我拼接了一个拥有无参构造函数的类的代码,需要返回这个类的实例

3.我拼接了一个方法代码,需要返回这个方法的委托

对于之前的DynamicCompile_1来说,我要完成这3个工作都需要额外的编写一些重复的,不必要的代码,这对我来说是一件令我很烦躁的事

所以我想要3个方法代替他们

Type type = CompileClass("public static class  aaa { public static User GetUser() { new User(); } }", usingTypes);
object obj = CompileObject("public class bbb : ICloneable { public object Clone() { return new User(); } }", usingTypes);
Func<object, string> func = CompileMethod<Func<object, string>>("public object GetUser() { return new User(); }", usingTypes);

 

  • 封装

先来看看现在的类

using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace blqw
{
    public class DynamicCompile_1
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="code">需要编译的C#代码</param>
        /// <param name="usingTypes">编译代码中需要引用的类型</param>
        /// <returns></returns>
        public static Assembly CompileAssembly(string code, params Type[] usingTypes)
        {
            CompilerParameters compilerParameters = new CompilerParameters();//动态编译中使用的参数对象
            compilerParameters.GenerateExecutable = false;//不需要生成可执行文件
            compilerParameters.GenerateInMemory = true;//直接在内存中运行


            //添加需要引用的类型
            HashSet<string> ns = new HashSet<string>();//用来保存命名空间,

            foreach (var type in usingTypes)
            {
                ns.Add("using " + type.Namespace + ";" + Environment.NewLine);//记录命名空间,因为不想重复所以使用了HashSet
                compilerParameters.ReferencedAssemblies.Add(type.Module.FullyQualifiedName);//这个相当于引入dll
            }

            code = string.Concat(ns) + code;//加入using命名空间的代码,即使原来已经有了也不会报错的

            //声明编译器
            using (CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider())
            {
                //开始编译
                CompilerResults cr = objCSharpCodePrivoder.CompileAssemblyFromSource(compilerParameters, code);

                if (cr.Errors.HasErrors)//如果有错误
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("编译错误:");
                    foreach (CompilerError err in cr.Errors)
                    {
                        sb.AppendLine(err.ErrorText);
                    }
                    throw new Exception(sb.ToString());
                }
                else
                {
                    //返回已编译程序集
                    return cr.CompiledAssembly;
                }
            }
        }
    }
}
DynamicCompile_1

相关文章: