C# 将字符串解析为 Func<T, bool>

MyB*_*g18 3 c#

我正在尝试解析字符串以创建 Func 实例。

public class A
{
    public int fieldA { get; private set; }
    public bool fieldB { get; private set; }
    public List<int> fieldC { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

检查A类实例的条件:

{
    "Type" : "A"
    "Condition" : "fieldA > 0 && fieldB == true"
}
Run Code Online (Sandbox Code Playgroud)

当然可以修改字符串的格式,以便于解析。

我想要创建的实际上是:

{
    "Type" : "A"
    "Condition" : "fieldA > 0 && fieldB == true"
}
Run Code Online (Sandbox Code Playgroud)

解析condition字符串不会很困难,但是由于A实例太多,因此在检查条件时使用反射是不可取的。我想要做的是预先从字符串“构造”这个函数并将其缓存在某处,并在我想检查条件时调用缓存函数。

你能给我什么建议吗?

Mat*_*ili 9

使用System.Linq.Dynamic.Core您可以执行以下操作:

public bool TestCondition(A obj, string condition)
{
    var expr = DynamicExpressionParser.ParseLambda<A, bool>(ParsingConfig.Default, false, condition, new object[0]);
    var func = expr.Compile();
    return func(obj);
}
Run Code Online (Sandbox Code Playgroud)

并像这样调用它:

var testResult = TestCondition(anInstanceOfA, "fieldA > 0 && fieldB == true");
Run Code Online (Sandbox Code Playgroud)

如果要在表达式中使用局部变量,可以执行以下操作:

public static bool TestCondition(A obj, string condition, IDictionary<string, object> args)
{
    var expr = DynamicExpressionParser.ParseLambda(new ParameterExpression[] { Expression.Parameter(typeof(A)) },
        typeof(bool),
        condition,
        new object[] { args });

    var func = expr.Compile();
    return (bool)func.DynamicInvoke(obj);
}
Run Code Online (Sandbox Code Playgroud)

并像这样调用它:

var locals = new Dictionary<string, object>();
locals.Add("myInt", 0);
locals.Add("myBool", true);
var check = TestCondition(obj, "fieldA > myInt && fieldB == myBool", locals);
Run Code Online (Sandbox Code Playgroud)

您还可以使该方法通用,以便您可以在其他情况下重用它:

public static TOut TestCondition<TIn, TOut>(TIn obj, string condition, IDictionary<string, object> args)
{
    var expr = DynamicExpressionParser.ParseLambda(new ParameterExpression[] { Expression.Parameter(typeof(TIn)) },
        typeof(TOut),
        condition,
        new object[] { args });

    var func = expr.Compile();
    return (TOut)func.DynamicInvoke(obj);
}

.
.
.
TestCondition<A, bool>(obj, "fieldA > myInt && fieldB == myBool", locals)
Run Code Online (Sandbox Code Playgroud)