在运行时编译和使用类

本文关键字:运行时 编译 | 更新日期: 2023-09-27 18:06:15

我正在开发一种规则引擎,其中用户将规则定义为一组条件和操作。然后将这些条件和操作解析为要执行的代码。我能够生成代码没有任何问题。我被困在编译它然后加载类的地方了。

我如何采取一串动态生成的源代码,并在运行时编译它?

我该如何执行这段代码?

我设想能够有一个静态的规则列表,随着添加规则而更新。比如:

static Dictionary<string, Rule> Rules { get; set; }
static void RefreshRules ()
{
    var newRules = DataLayer.GetRules().Where(r => !this.Rules.ContainsKey(r.Name));
    foreach (var rule in newRules)
    {
        this.Rules[rule.Name] = CompileRule(rule.Code);
    }
}
或者我重新编译一个程序集,然后重新加载到我已经运行的应用程序?

在运行时编译和使用类

我建议您使用表达式树而不是动态编译代码。

当您编译某些源代码时,生成的程序集将被粘贴到主应用程序中,并且不能再分离。这将导致内存使用量的增长,并导致潜在的危险行为。表达式树是为您的目标创建的。

一些粗略的例子(编译源代码,创建实例,使用反射调用带参数的方法):

CodeDomProvider P = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("C#");
CompilerParameters O = new CompilerParameters();
O.GenerateInMemory = true;
O.ReferencedAssemblies.Add(@"System.dll");
//O.ReferencedAssemblies.Add(@"System.Net.dll");
O.IncludeDebugInformation = false;
CompilerResults R = P.CompileAssemblyFromSource(O, new string[] { "using System; using System.Reflection; namespace ABC.TestXXX {     // your source code goes here }" });
Assembly _B_ = R.CompiledAssembly;
// create an instance
object YY = _B_.CreateInstance("ABC.TestXXX.MyClass");
// call method returning bool and taking one string and one object
YR = (bool)_B_.GetType("ABC.TestXXX.MyClass").GetMethod("TestB").Invoke(YY, new object[] { "Hallo", SomeObject });

  • http://msdn.microsoft.com/en-us/library/system.codedom.compiler.codedomprovider%28v=VS.100%29.aspx
  • http://msdn.microsoft.com/en-us/library/system.codedom.compiler.compilerparameters.aspx

对于您的情况,您可以使规则Action<>/delegate依次调用编译的方法并将其放入Dictionary<>…所以当调用它们的时候,它变得更容易读了