2016-08-16 5 views
0

Так что я не совсем понимаю это. Я пытаюсь создать MethodCallExpression, но я получаю ошибку времени выполнения, заявляя, что метод не может быть вызван именно с тем типом, который он ожидает? Я довольно новичок в деревьях выражений, поэтому я уверен, что у меня есть что-то в обратном направлении, но почти каждый пример, который я пытаюсь адаптировать, приводит к этому.Не удается вызвать метод типа A с параметром A?

using System; 
using System.Linq; 
using System.Linq.Expressions; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var helper = new Helper(); 
      var expr = helper.GetMatchExpr<TestClass>(t => t.Name, "foo"); 
     } 
    } 

    public class Helper 
    { 
     public Expression<Func<T, bool>> GetMatchExpr<T>(Expression<Func<T, object>> member, string searchValue) 
     { 
      var memberExpr = member.Body as MemberExpression; 
      if (memberExpr == null) 
       throw new ArgumentException("Expected member expression"); 

      var parameter = Expression.Parameter(typeof(T), "type"); 
      var property = Expression.Property(parameter, memberExpr.Member.Name); 
      var propertyExpr = Expression.Convert(property, typeof(string)); 

      var matchMethod = typeof(Helper).GetMethod("IsMatch", new[] { typeof(object), typeof(string) }); 

      var valueExpr = Expression.Constant(searchValue, typeof(string)); 
      var matchExpr = Expression.Call(property, matchMethod, propertyExpr, valueExpr); // throws exception 

      return Expression.Lambda<Func<T, bool>>(matchExpr, parameter); 
     } 

     public bool IsMatch(object input, string searchValue) 
     { 
      if (input == null) 
       return true; 

      var qWords = GetWords(searchValue); 
      var pWords = GetWords(input.ToString()); 

      return (
       from qWord in qWords 
       from pWord in pWords 
       where qWord.Equals(pWord, StringComparison.OrdinalIgnoreCase) 
       select qWord).Any(); 
     } 

     public string[] GetWords(string input) 
     { 
      return string.IsNullOrEmpty(input) 
       ? new string[0] 
       : input.Split(' '); 
     } 
    } 

    public class TestClass 
    { 
     public string Name { get; set; } 
     public string Age { get; set; } 
    } 
} 

Исключение составляет

Дополнительная информация: Метод 'Логическое IsMatch (System.Object)' объявили о типе 'ConsoleApplication4.Helper`1 [ConsoleApplication4.TestClass]' не может быть названо с экземпляром типа 'System.Object'

Чтобы ответить на некоторые вопросы:

Как упражнение, я пытаюсь создать этот класс, где вы можете указать коллекцию свойств объекта T, которая будет включена в поиск. Итак, как только все эти свойства установлены, вы вызываете Apply (...) и выполняете итерацию через набор выражений членов, захватываете их значение, разделяете на отдельные слова, делаете то же самое с фразой запроса и затем возвращаете любой объект который имеет любые свойства, которые соответствуют любому из слов.

Я прошел через, вероятно, 5 или 6 различных примеров, которые были близки к тому, что я пытался достичь, и это просто то, что я сейчас нахожу.

Так что, я думаю, я не совсем понимаю, что «вызывать IsMatch по результату propertyExpr». Означает ли это, что он использует результат, например result.IsMatch или IsMatch (результат)? Если это последний, нельзя ли использовать что-либо в качестве объекта?

+1

«Я получаю ошибку времени выполнения, заявляя, что метод не может быть вызван именно таким типом, который он ожидает» - нет, вы получаете исключение, заявив, что вы не можете вызвать «Помощник .IsMatch' на экземпляре 'System.Object'. Это не поможет, что вы не предоставили [mcve], поэтому мы не можем воспроизвести проблему. –

+0

Обновлено. Так что, очевидно, меня смущают требуемые параметры. – Sinaesthetic

+0

Это все еще не является полным, поскольку в него не входит PredicateBuilder, и это излишне подробный - почему есть класс 'Main', который вы просто создаете и запускаете в своем классе' Program', например?Я сильно подозреваю, что вы можете получить это от неполного примера из 122 строк до полного примера на основе 75 строк. –

ответ

1

Посмотрите на вашего выражения вызова метода:

var matchExpr = Expression.Call(property, matchMethod, propertyExpr, valueExpr); 

Первый аргумент является объектом вызова метода - то, что вы пытаетесь вызвать IsMatch дальше. Теперь IsMatch объявлен в вашем вспомогательном классе, поэтому вы должны называть его экземпляром этого класса. Например:

var targetExpr = Expression.Constant(this, typeof(Helper)); 
var matchExpr = Expression.Call(targetExpr, matchMethod, propertyExpr, valueExpr); 

Это удаляет исключение - но это все еще не ясно, что какой-либо из этого кода будет помогать вам. Наличие представления дерева выражений запроса обычно полезно, когда это дерево выражений может быть преобразовано в какую-либо другую форму, например. SQL ... но ни один поставщик LINQ не узнает, что делает ваш метод Helper.IsMatch.

Если ваша цель состояла в том, чтобы выполнить всю соответствующую работу в базе данных, это решение не поможет вам. Если ваша цель состояла в том, чтобы просто выполнить соответствующую работу, вы могли бы сделать это намного проще, используя LINQ to Objects, и просто вызывая методы соответствующим образом и используя делегаты там, где это необходимо, без использования IQueryable<T>.

+0

Спасибо тонну. Ну, по крайней мере, я понимаю это немного лучше. Часть, которую я вырезал, использует это как шаг для построения дерева двоичного выражения. У меня была рабочая версия (хотя я не тестировал ее на EF), но основной запрос казался, что он будет работать (цепочка OR), и источник, из которого я получил его, утверждал, что это будет:/ – Sinaesthetic

+0

конечная цель была абстракция, которая помогает конвертировать некоторые строки фильтров, которые считываются из запроса GET на веб-странице. Я пытаюсь упростить процесс фильтрации на «одобренных» полях. Первоначально он делал это в готовой коллекции (после вызова базы данных), но это создает проблему с поисковым вызовом. Между тем, я использовал как возможность познакомиться с деревьями выражений. – Sinaesthetic

+0

@ Синестетика: Определенно хорошо быть знакомым с деревьями выражений, но вам понадобится немного больше работы, чтобы это можно было сделать в базе данных, к сожалению :( –

 Смежные вопросы

  • Нет связанных вопросов^_^