Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时编译和使用类_C#_Code Generation_Metaprogramming - Fatal编程技术网

C# 在运行时编译和使用类

C# 在运行时编译和使用类,c#,code-generation,metaprogramming,C#,Code Generation,Metaprogramming,我正在开发一种规则引擎,用户将规则定义为一组条件和操作。然后将这些条件和操作解析为要执行的代码。我能够生成没有任何问题的代码。我陷入了编译它然后加载类的困境 如何获取动态生成的源代码字符串并在运行时编译它 然后我如何执行该代码 我设想能够有一个静态的规则列表,随着规则的添加而更新。比如: static Dictionary<string, Rule> Rules { get; set; } static void RefreshRules () { var newRules

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

如何获取动态生成的源代码字符串并在运行时编译它

然后我如何执行该代码

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

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);
    }
}
静态字典规则{get;set;}
静态无效刷新规则()
{
var newRules=DataLayer.GetRules().Where(r=>!this.Rules.ContainsKey(r.Name));
foreach(newRules中的var规则)
{
this.Rules[rule.Name]=编译器文件(rule.Code);
}
}
或者我会重新编译程序集,然后将其重新加载到已经运行的应用程序中?

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

一些包含详细信息的链接:


对于您的情况,您可以将规则设置为Action/delegate,然后调用已编译的方法并将其放入字典中。。。因此,当调用它们时,它变得相当可读。我建议您使用,而不是动态编译代码


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

从这里开始:;我过去使用过CodeDom,但手头没有代码示例可以提供正确的答案。请检查您不想使用Drools等规则引擎的原因?您是否考虑过直接使用
System.Reflection.Emit
?有时它比表达式树更容易。
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 });