2010-01-16 7 views
2

Я столкнулся с проблемой ниже и задаюсь вопросом, кто-то там сможет помочь. Я добавил комментарии к коду, чтобы сделать его понятным, но дайте мне знать, если вам нужна дополнительная информация или проблема неясна.Деревья выражений в .NET 4.0: Expression.Call не может найти метод «get_Item» в списке типов <T>

Большое спасибо!

Редактировать: меня попросили суммировать проблему в тексте, так что вот оно: при обстоятельствах, описанных в приведенном ниже коде, Expression.Call (...) генерирует следующее исключение: «No method» get_Item 'существует на типа 'System.Collections.Generic.List`1'[System.Double]»

Я считаю, что метод существует в типе, как показано здесь:

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

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

У меня есть lso сделал название немного более описательным; извините, если первоначальный вопрос не был ясен.

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()); 
    } 
+0

Можете ли вы вкратце описать в тексте, что такое точная проблема (в отличие от описания ее в комментариях кода)? Что вы ожидали и каковы были результаты? – Eilon

+0

Проще говоря, Expression.Call выдает следующее исключение: «Нет метода get_Item существует в типе« System.Collections.Generic.List'1 [System.Double] ». Я считаю, что такой метод действительно существует в этом типе. –

+0

Я только что добавил это к описанию проблемы. –

ответ

5

перегрузки вы используете только для статических методов (см документации: http://msdn.microsoft.com/en-us/library/bb351107.aspx). И «get_Item» явно не является статическим методом. Итак, вам нужно использовать другой метод перегрузки. Попробуйте это, например:

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

Это официально: я собираюсь добавить тег «beginner» на мои вопросы с этого момента. +1 (и большое спасибо) за то, что он ответил на это «дух!» (перед тем, как начать писать, внимательно прочитайте документы). –

+0

Если вы задаете вопросы о деревьях выражений, вы определенно не новичок :-) Это довольно сложная тема. –

+0

@ Саша Он * может быть * новичком в Деревнях выражений) рад видеть девушек на этом форуме, от Microsoft и русских! вах. – serhio