从字符串创建lambda表达式

可能重复:
有一种简单的方法可以将(lambda表达式)字符串解析为Action委托吗?

我想将lambda表达式存储为配置文件中的字符串,并在运行时将这些字符串动态加载到C#中的lambda表达式中。 我的目标是配置和注入规则。 任何可用于从字符串创建lambda表达式的实用程序?

对于同一目标,还有其他轻量级解决方案吗?

如果您提前知道表达式的类型,那么您可以将它们编译为类的一部分,然后将它们从生成的程序集中拉回来。

这是一个示例(使用表达式获取字符串并返回bool)并运行生成的规则。

c:\ temp \ rules.txt的内容是这样的:

file => file.Length == 0 file => System.IO.Path.GetExtension(file) == ".txt" file => file == null 

然后得到的输出是这样的:

 Rules found in file: file => file.Length == 0, file => System.IO.Path.GetExtension(file) == ".txt", file => file == null, Checking rule file => (file.Length == 0) against input c:\temp\rules.txt: False Checking rule file => (GetExtension(file) == ".txt") against input c:\temp\rules.txt: True Checking rule file => (file == null) against input c:\temp\rules.txt: False 

资源:

 using System; using System.Xml.Linq; using System.Linq; using System.IO; using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Reflection; using System.Linq.Expressions; class Program { private const string classTemplate = @" using System; using System.Linq.Expressions; public static class RulesConfiguration {{ private static Expression>[] rules = new Expression>[] {{ {0} }}; public static Expression>[] Rules {{ get {{ return rules; }} }} }} "; static void Main(string[] args) { var filePath = @"c:\temp\rules.txt"; var fileContents = File.ReadAllLines(filePath); // add commas to the expressions so they can compile as part of the array var joined = String.Join("," + Environment.NewLine, fileContents); Console.WriteLine("Rules found in file: \n{0}", joined); var classSource = String.Format(classTemplate, joined); var assembly = CompileAssembly(classSource); var rules = GetExpressionsFromAssembly(assembly); foreach (var rule in rules) { var compiledToFunc = rule.Compile(); Console.WriteLine("Checking rule {0} against input {1}: {2}", rule, filePath, compiledToFunc(filePath)); } } static Expression>[] GetExpressionsFromAssembly(Assembly assembly) { var type = assembly.GetTypes().Single(); var property = type.GetProperties().Single(); var propertyValue = property.GetValue(null, null); return propertyValue as Expression>[]; } static Assembly CompileAssembly(string source) { var compilerParameters = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true, ReferencedAssemblies = { "System.Core.dll" // needed for linq + expressions to compile }, }; var compileProvider = new CSharpCodeProvider(); var results = compileProvider.CompileAssemblyFromSource(compilerParameters, source); if (results.Errors.HasErrors) { Console.Error.WriteLine("{0} errors during compilation of rules", results.Errors.Count); foreach (CompilerError error in results.Errors) { Console.Error.WriteLine(error.ErrorText); } throw new InvalidOperationException("Broken rules configuration, please fix"); } var assembly = results.CompiledAssembly; return assembly; } } 

看看Dynamic Linq吧 。 这是一个老post,但总是很有用。