2011-08-17 10 views
8

string.IndexOf("substring", StringComparison.OrdinalIgnoreCase)の式ツリーをどのように構築すればよいですか?String.IndexOfメソッドの式ツリー

第2引数なしで、私はそれを働かせることができます:StringComparison.OrdinalIgnoreCase。これらは、これまでのところ、私の試みです:

var methodCall = typeof (string).GetMethod("IndexOf", new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Constant("StringComparison.OrdinalIgnoreCase", typeof (Enum))}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

もこれを試してみました:私はOrdinalIgnoreCaseパラメータを無視した場合

var methodCall = typeof (string).GetMethod(method, new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Parameter(typeof(Enum) , "StringComparison.OrdinalIgnoreCase")}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

私はそれが働いて得ることができることを覚えておいてください。

ありがとうございました

+2

これまでどおり、問題が発生したときに何がうまくいかないのかを教えてください。例外、コンパイル時のエラー、間違った動作などがありますか?何らかのエラーが発生した場合、エラーは何ですか? –

+0

申し訳ありません。次回は質問をするときにそれを覚えておきます。私はArgumentExceptionを取得していました。 – ashokgelal

+0

助けてください:[どのように私を作成する - 表現 - ツリーを表現するために文字列を含む](http://stackoverflow.com/questions/278684/how-do-i-create- a-expression-tree-to-represent-string-containsterm-in-c) – nawfal

答えて

11

私には2つの問題があると思われます。

最初は、あなたが方法を取得している方法です - あなたはは、単一の文字列パラメータ、代わりの二つのパラメータを持つ1と方法のためを求めている:第二は

var methodCall = typeof (string).GetMethod("IndexOf", 
          new[] { typeof (string), typeof(StringComparison) }); 

あなたが与えている - それは一定ではなく、文字列の実際の値でなければなりません:

Expression[] parms = new Expression[] { right, 
    Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

編集:ここでは完全な作業のサンプルです:

using System; 
using System.Linq.Expressions; 

class Test 
{ 
    static void Main() 
    { 
     var method = typeof (string).GetMethod("IndexOf", 
       new[] { typeof (string), typeof(StringComparison) }); 

     var left = Expression.Parameter(typeof(string), "left"); 
     var right = Expression.Parameter(typeof(string), "right"); 

     Expression[] parms = new Expression[] { right, 
       Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

     var call = Expression.Call(left, method, parms); 
     var lambda = Expression.Lambda<Func<string, string, int>> 
      (call, left, right); 

     var compiled = lambda.Compile(); 
     Console.WriteLine(compiled.Invoke("hello THERE", "lo t")); 
    } 
} 
+0

'contains'メソッドに対して同じことをする方法はありますか? – atp9

+0

@ atp9:はい。何を試しましたか、何がうまくいかなかったのですか? –

+0

私はこのようなものを試しました: 'MethodInfo method = typeof(string)。GetMethod( "Contains"、new [] {typeof(string)、typeof(StringComparison)}); var式のボディ= System.Linq.Expressions.Expression.Call(小道具、メソッド、新しい[] {値の互換性、System.Linq.Expressions.Expression.Constant(StringComparison.OrdinalIgnoreCase)}); 'これは私にエラーを返します – atp9

0

私はそれの残りの部分をチェックしませんでしたが、唯一の列挙は、問題提起する場合:

Expression.Constant(StringComparison.OrdinalIgnoreCase) 

または

Expression.Constant(Enum.Parse(typeof(StringComparison), "OrdinalIgnoreCase"), typeof(Enum)); 

をそして、あなたはより多くのオプションを持っています。または私の答えhereをチェックしてください。

編集:paranthesisを忘れました。

3

それは、このようなラムダを経由してそれを得ることであろう最も簡単な方法:

//the compiler will convert the lambda into an expression 
Expression<Func<string, string, int>> expression = (s1, s2) => s1.IndexOf(s2, StringComparison.OrdinalIgnoreCase); 
//compile the expression so we can call it 
var func = expression.Compile(); 
//outputs 2 
Console.WriteLine(func("Case Sensitive", "se sensitive")); 

これは、はるかに読みやすく、保守し、手動式ツリーを構築するよりもです。

私は、表現木を手動で構築することに直接関わる人々の数に絶えず驚いています。コンパイラがあなたのために仕事をすることができるときは必要ありません。

+2

+1、コンパイラがあなたのためにそれを行うことができるときに手動で式ツリーを構築する理由はありません –

+1

@Thomas:はい、しかし、ここからは 'left'と' right'がどこから来ているのか分かりません。おそらく 'string'ではなく' Expression'の型です。 –

+0

これは良い方法ですが、私が作業しているライブラリ(https://github.com/ashokgelal/NetFilterFramework)は、手動で式ツリーを構築することによって構築されています。今のところ、文字列比較メソッド呼び出しを追加するだけですが、lambdaを使用してすべてをリファクタリング/書き直す必要があるかもしれません。 – ashokgelal