2011-08-20 83 views
2

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

如何获取一串动态生成的源代码并在运行时进行编译?

我该如何执行该代码?

我想能够拥有一个静态的规则列表,这些规则会随着规则的添加而更新。喜欢的东西:

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); 
    } 
} 

或者我会重新编译的程序集,然后重新放回我已经在运行的应用程序?

+0

从这里开始:http://msdn.microsoft.com/en-us/library/650ax5cx.aspx;我过去使用过CodeDom,但没有代码示例方便正确的答案。 –

+0

检出http://stackoverflow.com/questions/5766373/how-does-linqpad-compile-code –

+0

是否有你不想使用规则引擎的原因,比如Drools? – Amy

回答

5

我,你会推荐他们时变得相当可读使用Expression Trees而不是动态编译代码。

当您编译某些源代码时,生成的程序集会粘贴到主应用程序中,并且无法再分离。这导致了越来越多的内存使用,并导致潜在的危险行为。表达式树已经被创建,只用于像你的目标。

3

有些粗糙例如(编译源代码,创建实例,调用与使用反射PARAMS法):

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 }); 

与细节的某些链接:

对于你的情况,你可以制定规则的行动<> /代表这反过来又调用编译方法,把那些进入词典<> ...所以它调用等