2016-08-16 6 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; } 
    } 
} 

例外はある

追加情報: 'ConsoleApplication4.Helper`1は[ConsoleApplication4.TestClass]' を呼び出すことができないタイプ で宣言メソッド 'ブールIsMatch(System.Objectの)' :タイプのインスタンス 'のSystem.Object' で

は、いくつかの質問に答えるために

練習として、このクラスを作成して、オブジェクトTに検索に含めるプロパティのコレクションを指定できるようにしています。したがって、これらのプロパティがすべて設定されると、Apply(...)を呼び出すと、メンバー式のコレクションを反復して値を取得し、個々の単語に分割し、クエリフレーズで同じことを行い、オブジェクトを返しますいずれかの単語に一致するプロパティを持つ。

私は達成しようとしていたものに近い5つまたは6つの異なる例を見てきましたが、これは現時点での私のところです。

私は「propertyExprの結果でIsMatchを呼び出す」ことをよく理解していないと思います。それはresult.IsMatchやIsMatch(result)のような結果を使用していることを意味しますか?それが後者なら、何もオブジェクトとして使えないはずですか?あなたのメソッド呼び出し式で

+1

"メソッドが期待通りの型で呼び出すことができないというランタイムエラーが発生しました" - いいえ、インスタンス上でヘルパー.IsMatch'を呼び出すことができないという例外が発生しています'System.Object'のあなたは[mcve]を提供していないので、問題を再現することはできません。 –

+0

更新されました。明らかに、私は必要なパラメータによって混乱しています。 – Sinaesthetic

+0

PredicateBuilderが含まれていないため、これはまだ完全ではなく、不必要に冗長です。なぜなら、 'Program'クラスのインスタンスを作成して実行する' Main'クラスがあるのはなぜですか?私はあなたが不完全な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

最終目標Webページ上のGETリクエストから読み込まれたいくつかのフィルタ文字列を変換するのに役立つ抽象化でした。私は "承認された"フィールドでフィルタリングのプロセスを単純化しようとしています。もともと(データベース呼び出しの後で)完成したコレクションでそれを行いましたが、それはページングに問題があります。その間、私はExpression Treeに慣れる機会として使っていました。 – Sinaesthetic

+0

@Sinaesthetic:表現木に精通しているのは間違いありませんが、残念なことにデータベースでそれを行うにはもう少し作業が必要です。 –

関連する問題