既然要使用动态编译,那么为他封装一个调用类,在调用时省去大量不必要的编码操作还是很有必要的。
- 为什么要封装?
其实这个说起来很简单,就是发现现有的动态编译类在使用过程中显得并不是那么好用。我觉得我可以让他变的更易使用。
所以我应该重新封装了一个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; } } } } }