c# - .NET 4.0 中的表达式树 : Expression. 调用无法在类型 List<T> 中找到方法 "get_Item"

标签 c# .net-4.0 lambda expression-trees

我遇到了以下问题,想知道是否有人能够提供帮助。我已在代码中添加了注释,使其不言自明,但如果您需要更多信息或问题不清楚,请告诉我。

提前非常感谢!

编辑:我被要求用文本总结问题,所以这里是:在下面代码中描述的情况下,Expression.Call(...) 抛出以下异常:“没有方法'get_Item'存在于类型“System.Collections.Generic.List`1[System.Double]”上”

我相信该方法确实存在于类型中,如下所示:

List<double> sampleList = new List<double>();

Console.WriteLine(sampleList.GetType().GetMethod("get_Item") == null); // False

我还使标题更具描述性;如果最初的问题不清楚,抱歉。

public class ExpressionExample
{
    public void Main()
    {
        Expression<Func<List<double>, double>> component = u => u[0];
        Console.WriteLine(component.Body.NodeType); // Prints out "Call"
        Console.WriteLine(component.Body); // Prints out "u.get_Item(0)"

        MethodCallExpression copyGetComponent = CopyCallExpression(component.Body as MethodCallExpression);
    }

    public MethodCallExpression CopyCallExpression(MethodCallExpression callExpression)
    {
        if (callExpression == null)
            return null;

        // Some tests
        Console.WriteLine(callExpression.Method.Name); // "get_Item"
        List<double> sampleList = new List<double>();
        Console.WriteLine(sampleList.GetType().GetProperty("get_Item") == null); // True
        Console.WriteLine(sampleList.GetType().GetProperty("Item") == null); // False
        Console.WriteLine(sampleList.GetType().GetMethod("get_Item") == null); // False (1)
        Console.WriteLine(sampleList.GetType().GetMethod("Item") == null); // True            
        Console.WriteLine(sampleList.GetType().FullName == callExpression.Method.DeclaringType.FullName); // True! (2)

        // However...
        Type[] argTypes = (from argument in callExpression.Arguments select argument.Type).ToArray();
        // Next line throws an exception: No method 'get_Item' exists on type 'System.Collections.Generic.List`1[System.Double]'
        return Expression.Call(callExpression.Method.DeclaringType, callExpression.Method.Name, argTypes, callExpression.Arguments.ToArray());

        // How does this come together with items (1) and (2) above?
    }
}

编辑:我想我已经找到了解决我眼前问题的解决方法;发布它以防其他人遇到这个问题:

public class ExpressionExample
{
    public void Main()
    {
        Expression<Func<List<double>, double>> invokeProp = u => u[0];

        Console.WriteLine(invokeProp); // u => u.get_Item(0)
        Console.WriteLine(invokeProp.Body); // u.get_Item(0)
        Console.WriteLine(invokeProp.Body.NodeType); // Call

        Expression copyGetComponent = CopyCallExpression(invokeProp.Body as MethodCallExpression);

        LambdaExpression copyInvokeProp = Expression.Lambda(copyGetComponent, invokeProp.Parameters);

        Console.WriteLine(copyInvokeProp); // u => u.Item[0]
        Console.WriteLine(copyInvokeProp.Body); // u.Item[0]
        Console.WriteLine(copyInvokeProp.Body.NodeType); // Index

        // Technically different expressions, but I suppose
        // they should be "functionally equal" though
    }

    public Expression CopyCallExpression(MethodCallExpression callExpression)
    {
        if (callExpression == null)
            return null;

        MethodInfo info = callExpression.Method;

        if (info.Name == "get_Item")
        {
            PropertyInfo propInfo = typeof(List<double>).GetProperty("Item");
            return Expression.MakeIndex(callExpression.Object, propInfo, callExpression.Arguments);
        }

        if (info.IsStatic)
            return Expression.Call(info, callExpression.Arguments);

        Type[] argTypes = (from argument in callExpression.Arguments select argument.Type).ToArray();
        return Expression.Call(info.DeclaringType, info.Name, argTypes, callExpression.Arguments.ToArray());
    }

最佳答案

您使用的重载仅适用于静态方法(请参阅文档: http://msdn.microsoft.com/en-us/library/bb351107.aspx )。而“get_Item”显然不是一个静态方法。 因此,您需要使用不同的方法重载。试试这个,例如:

return Expression.Call(callExpression.Object, callExpression.Method, callExpression.Arguments.ToArray()); 

关于c# - .NET 4.0 中的表达式树 : Expression. 调用无法在类型 List<T> 中找到方法 "get_Item",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2079077/

相关文章:

c# - ConcurrentQueue<T>.TryPeek() 的用例是什么?

c# - 构建 LINQ 表达式树 : how to get variable in scope

c# - MVC Controller 方法参数始终为空

c# - 通过 C++ 64 位 dll 在 64 位 .net 应用程序中调用 PInvoke

multithreading - 多线程WMI调用-如何最好地处理此问题?

c# - 为什么有必要对 'manually' 求值或强制转换对象的类型?

C++11 lambda : mixed capture list

c# - 从字符串构建 Linq 排序表达式结果为 'Expression of "system.int3 2"can not be used for return type "System.Object"'

c# - 将文件上传到 Azure 存储会导致错误 : Timeouts are not supported on this stream

c# - 如何在Silverlight 5控件中显示HTML内容