创建一个表达式,该表达式将计算委托的结果,并返回结果或备用(视情况而定)

本文关键字:表达式 结果 返回 视情况而定 备用 一个 计算 创建 | 更新日期: 2023-09-27 17:56:44

我想使用 getter 表达式检索属性的值,但在该表达式中,我想计算一个谓词,并且仅在谓词计算结果为 false 时才返回属性的值,否则返回一个常量。

大致如下(部分使用此处的代码):

Expression<Func<U, bool>> exp = FuncToExpression(predicate);
var instance = Expression.Parameter(propertyInfo.DeclaringType, "instance");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
var getLamba = Expression.Lambda(convert, instance);
var evaluate = Expression.Condition(exp, getLamba, Expression.Constant(alternate));
var lambda = Expression.Lambda(evaluate, instance);
return (Func<T, object>)lambda.Compile();

这里的任何帮助将不胜感激

编辑
根据乔恩的评论,更多细节:

我在评估变量上收到以下错误:{"参数必须是布尔值"}

这是FuncToExpression方法:

private static Expression<Func<U, bool>> FuncToExpression<U>(Func<U, bool> predicate)
{
    return argument => predicate(argument);
} 

编辑 2
完整示例:

public class Test
{
    public static void Main(string[] args)
    {
        TestPredicate test = new TestPredicate();
        test.Number = 11;
        Func<TestPredicate, object> callDelegate;
        PropertyInfo info = typeof(TestPredicate).GetProperties().Where(a => a.Name == "Number").FirstOrDefault();
        Func<int, bool> f = (x => x > 10 ? true : false);
        if (info != null)
        {
            callDelegate = CreateValueGetDelegate<TestPredicate, int, int>(info, f, -1);
            var item = (int) callDelegate(test);
            Console.WriteLine(item); // expecting -1 here
        }
        Console.Read();
    }
    private static Func<T,object> CreateValueGetDelegate<T,U, S>(PropertyInfo propertyInfo, Func<U, bool> predicate, S alternate)
    {
        if (typeof(T) != propertyInfo.DeclaringType)
        {
            throw new ArgumentException();
        }
        Expression<Func<U, bool>> exp = FuncToExpression(predicate);
        var instance = Expression.Parameter(propertyInfo.DeclaringType, "instance");
        var property = Expression.Property(instance, propertyInfo);
        var convert = Expression.TypeAs(property, typeof(object));
        var getLamba = Expression.Lambda(convert, instance);
        var evaluate = Expression.Condition(exp, getLamba, Expression.Constant(alternate));
        var lambda = Expression.Lambda(evaluate, instance);
        return (Func<T, object>)lambda.Compile();
    }
    private static Expression<Func<U, bool>> FuncToExpression<U>(Func<U, bool> predicate)
    {
        return argument => predicate(argument);
    }  
    public class TestPredicate
    {
        public int Number { get; set; }
    }
}

创建一个表达式,该表达式将计算委托的结果,并返回结果或备用(视情况而定)

如果你说出当前出了什么问题,那会有所帮助,但我认为你只需要摆脱第一个Lambda电话。我也对变量名称进行了一些更改:

Expression<Func<U, bool>> test = FuncToExpression(predicate);
var parameter = Expression.Parameter(propertyInfo.DeclaringType, "instance");
var property = Expression.Property(parameter, propertyInfo);
var trueOption = Expression.TypeAs(property, typeof(object));
var falseOption = Expression.Constant(alternative);
var conditional = Expression.Condition(test, trueOption, falseOption);
var lambda = Expression.Lambda<Func<T, object>>(conditional, parameter);
return lambda.Compile();

如果这不起作用,请告诉我们以何种方式 - 理想情况下,将简短但完整的示例程序编辑到您的问题中。

此扩展方法将允许您提供选择器(获取属性)、验证器(验证属性)和默认值:

public static P GetValueOrDefault<T, P>(this T item, Func<T, P> selector, Func<P, bool> validator, P defaultValue)
{
    if (item == null)
        return defaultValue;
    P value = selector(item);
    if (validator == null || !validator(value))
        return defaultValue;
    return value;
}