正在从字符串创建lambda表达式
本文关键字:lambda 表达式 创建 字符串 | 更新日期: 2023-09-27 18:20:11
可能重复:
有没有一种简单的方法可以将(lambda表达式)字符串解析为Action委托?
我想将lambda表达式作为字符串存储在配置文件中,并在运行时将这些字符串动态加载到C#中的lambda表达式中。我的目标是配置和注入规则。有任何实用程序可用于从字符串创建lambda表达式吗?
对于同一目标,是否还有其他轻量级解决方案?
如果您提前知道表达式的类型,那么您可以将它们作为类的一部分进行编译,然后将它们从生成的程序集中提取出来。
下面是一个执行并运行结果规则的示例(表达式采用字符串并返回布尔)。
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<Func<string, bool>>[] rules = new Expression<Func<string, bool>>[]
{{
{0}
}};
public static Expression<Func<string, bool>>[] 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<Func<string, bool>>[] GetExpressionsFromAssembly(Assembly assembly)
{
var type = assembly.GetTypes().Single();
var property = type.GetProperties().Single();
var propertyValue = property.GetValue(null, null);
return propertyValue as Expression<Func<string, bool>>[];
}
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。这是一个老帖子,但总是有用的。