【问题标题】:ParameterExpression of type 'MyClass' cannot be used for delegate parameter of type 'System.Object'“MyClass”类型的 ParameterExpression 不能用于“System.Object”类型的委托参数
【发布时间】:2015-08-13 00:01:46
【问题描述】:

我已经构建了一个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 类型,我可以以某种方式使用转换器吗?

【问题讨论】:

    标签: c# linq lambda expression-trees


    【解决方案1】:

    阅读评论后更新。

    完整代码,正在运行:

    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;}
    }
    

    【讨论】:

    • 这样我得到 'MyProperty' 不是 else leftFunc 分配 (left_element="MyProperty") 上的 'System.Object' 类型的成员
    • 然后走相反的路。把参数语句改回来,把Lambda语句改成Expression.Lambda&lt;Func&lt;MyClass,bool&gt;&gt;
    • MyClass 在编译之前是未知的,它可以是任何东西。
    • 你绝对需要使用Expression吗?在这种情况下,通过普通反射来做到这一点会容易得多
    • 我的目标是使用表达式过滤列表
    【解决方案2】:

    我以为你期待这样的事情。我使用泛型类型来避免你的参数异常

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多