类型为'MyClass'的ParameterExpression不能用于类型为'System.Object'的委托参数。

3
我已经构建了一个类型为 Func<object,bool> 的表达式树。但是当我尝试编译它时,出现了异常:

类型为 'MyClass' 的 ParameterExpression 不能用于类型为 'System.Object' 的委托参数

调用对象的类型在运行时是未知的。

Expression leftFunc, rightFunc;
var x = Expression.Parameter(t);
if (left_element.All(char.IsDigit)) 
    leftFunc = Expression.Constant(int.Parse(left_element));
else 
    leftFunc = Expression.PropertyOrField(x, left_element);
if (right_element.All(char.IsDigit)) 
    rightFunc = Expression.Constant(int.Parse(right_element));
else 
    rightFunc = Expression.PropertyOrField(x, right_element);
var result = Expression.Lambda<Func<object, bool>>(
        Expression.GreaterThan(leftFunc, rightFunc), x); //exception thrown on this line
return result;

xMyClass 类型的,我能以某种方式使用转换器吗?

2个回答

2

读完评论后更新。

完整的、可用的代码:

void Main()
{
    var method = something(typeof(MyClass), "propA", "propB");
    var classes = new List<MyClass>();
    classes.Add(new MyClass { propA = 1, propB = 2 }); // Should return false
    classes.Add(new MyClass { propA = 3, propB = 2 }); // Should return true
    classes.Add(new MyClass { propA = 2, propB = 2 }); // Should return false
    var res = classes.Where(method);
    res.Dump(); //Only class with propA = 3 && propB == 2 is returned
}

private Func<object, bool> something(Type t, string left_element, string right_element)
{
    var props = t.GetProperties();
    return (onObject) => {
        int left_int;
        object leftSide;
        if (!int.TryParse(left_element, out left_int))
        {
            leftSide = props.FirstOrDefault (p => p.Name == left_element).GetValue(onObject);
        } else {
            leftSide = left_int;
        }

        int right_int;
        object rightSide;
        if (!int.TryParse(right_element, out right_int))
        {
            rightSide = props.FirstOrDefault (p => p.Name == right_element).GetValue(onObject);
        } else {
            rightSide = left_int;
        }

        return Comparer.Default.Compare(leftSide, rightSide) > 0;       
    };
}

private class MyClass {
    public int propA {get;set;}
    public int propB {get;set;}
}

这样,当在else语句中赋值给leftFunc(left_element="MyProperty")时,会出现“'MyProperty'不是类型'System.Object'的成员”的错误。 - Szolnoki Ádám
然后走相反的路。将参数语句改回来,并将Lambda语句更改为 Expression.Lambda<Func<MyClass,bool>> - Rob
2
MyClass在编译时是未知的,它可以是任何东西。 - Szolnoki Ádám
你是否一定需要使用 Expression?如果是这样的话,通过普通反射来完成会更容易些。 - Rob
我的目标是使用表达式过滤一个列表。 - Szolnoki Ádám

0

我想你期望得到这样的结果。我使用了通用类型来避免您的参数异常。

Expression Example<T>(T customeType)
{
    Expression leftFunc, rightFunc;
    var x = Expression.Parameter(typeof(T), "x");

    string left_element = "Length";
    string right_element = "Length";

    if (left_element.All(char.IsDigit))
        leftFunc = Expression.Constant(int.Parse(left_element));
    else
        leftFunc = Expression.PropertyOrField(x, left_element);
    if (right_element.All(char.IsDigit))
        rightFunc = Expression.Constant(int.Parse(right_element));
    else
        rightFunc = Expression.PropertyOrField(x, right_element);
    var result = Expression.Lambda<Func<T, bool>>(
            Expression.GreaterThan(leftFunc, rightFunc), x); 
    return result;
}

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