2012-03-20 20 views
2

私は以下のコードを使用してメソッドを実行しています。しかし、私はケース非感受性のためにalllows Containsのオーバーライドを含むいくつかの文字列の拡張メソッドを使用しようとしています、たとえばStartsWithため、stringの標準的な方法のために働く:Reflectionを使用してパラメータで非ジェネリックな静的拡張メソッドを呼び出す方法

var method = "Contains"; 
var args = new object[] { "@", StringComparison.OrdinalIgnoreCase }; 

// This works when called 
var mi = m.Type.GetMethod(method, args.Select(a => a.GetType()).ToArray()); 
if (mi == null) { 
    // This does find the method, but causes an error on Expression.Call below 
    mi = typeof(Extensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(meth => meth.Name == method); 
} 

var c = args.Select(a => Expression.Constant(a, a.GetType())); 

return Expression.Lambda<Func<T, bool>>(Expression.Call(m, mi, c), e); 

私が受け取るエラーは次のとおりです。

Static method requires null instance, non-static method requires non-null instance.

どうすればこの問題を解決できますか?私は今、次のエラーを取得するものの、

public static bool Contains(this string source, string toCheck, StringComparison comp) { 
    return source.IndexOf(toCheck, comp) >= 0; 
} 

おかげ


EDITバラージュの解答ごとに更新

参考

は、ここにContains拡張したものです

Expression of type 'System.Linq.Expressions.PropertyExpression' cannot be used for parameter of type 'System.String' of method 'Boolean Contains(System.String, System.String, System.StringComparison)'

はここで参照のための完全な方法である:

public static Expression<Func<T, bool>> Build(string member, IEnumerable<object> memberArgs, string method, params object[] args) { 
    var e = Expression.Parameter(_type, "e"); 
    var memberInfo = 
     (MemberInfo) _type.GetField(member) ?? 
     (MemberInfo) _type.GetProperty(member) ?? 
     (MemberInfo) _type.GetMethod(member, (memberArgs ?? Enumerable.Empty<object>()).Select(p => p.GetType()).ToArray()); 
    Expression m; 

    if (memberInfo.MemberType == MemberTypes.Method) { 
     var a = memberArgs.Select(p => Expression.Constant(p)); 
     m = Expression.Call(e, (MethodInfo) memberInfo, a); 
    } 
    else { 
     m = Expression.MakeMemberAccess(e, memberInfo); 
    } 

    var mi = m.Type.GetMethod(method, args.Select(a => a.GetType()).ToArray()); 
    var c = args.Select(a => Expression.Constant(a, a.GetType())); 
    MethodCallExpression call; 

    if (mi != null) { 
     call = Expression.Call(m, mi, c); 
    } 
    else { 
     mi = typeof(Extensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(meth => meth.Name == method); 
     var newArgsList = c.ToList<object>(); 
     newArgsList.Insert(0, m); 
     c = newArgsList.Select(a => Expression.Constant(a, a.GetType())); 
     call = Expression.Call(null, mi, c); 
    } 

    return Expression.Lambda<Func<T, bool>>(call, e);   
} 

答えて

3

あなたはExpression.Callのインスタンスパラメータとしてnull ConsantExpressionを渡し、cの最初の引数としてmを追加する必要があります。

+0

私はこれを試しましたが、まだエラーが表示されます - 私は完全な方法で私のOPを更新しました。あなたの助けを借りて、もう一度このBalazsに感謝します:) –

+0

あなたのリストは 'List 'でなければなりません。 'm 'を最初の要素として追加し、' AddRange'で他の要素を追加します。 –

+0

ありがとうございます - それはそれを修正しました。将来あなたに迷惑をかけないように、表現木を構築するための良いリファレンスを知っていますか?私はちょうどそれの周りに私の頭を得るように見えることはできません。 –

関連する問題