从字符串创建Lambda表达式

7

可能是重复问题:
有没有一种简单的方法将(λ表达式)字符串解析为Action委托?

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

是否有其他轻量级解决方案可以实现同样的目标?


可能是重复的问题?https://dev59.com/93RB5IYBdhLWcg3wHkPi - MNIK
可能相关:https://dev59.com/Ul3Va4cB1Zd3GeqPD8sH#8328096 - sehe
投票关闭。顺便说一句:考虑使用更适合脚本编写的语言来编写您的逻辑,如LUA(https://dev59.com/4XM_5IYBdhLWcg3wp0-l),IronPython。 - Alexei Levenkov
关于Alexei使用脚本语言的想法,我建议看一下PowerShell,因为你在使用C#,而且很容易托管和使用PowerShell引擎。一个好的起始页面可以在http://msdn.microsoft.com/en-us/library/windows/desktop/ee706563(v=vs.85).aspx找到。 - James Manning
2个回答

5
如果您提前知道表达式的类型,那么您可以将它们编译为类的一部分,然后从生成的程序集中取回它们。
以下是一个例子(表达式以字符串为参数并返回布尔值),它实现了上述功能并运行了生成的规则。
假设 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;
    }
}

2

看一下Dynamic Linq。虽然这是一篇旧文章,但它仍然非常有用。


1
不错的选择 - 您可以安装NuGet包DynamicQuery(名称为“Dynamic Expression API”)-请参见http://nuget.org/packages/DynamicQuery - James Manning

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接