私は以下のコードを使用してメソッドを実行しています。しかし、私はケース非感受性のために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);
}
私はこれを試しましたが、まだエラーが表示されます - 私は完全な方法で私のOPを更新しました。あなたの助けを借りて、もう一度このBalazsに感謝します:) –
あなたのリストは 'List'でなければなりません。 'm 'を最初の要素として追加し、' AddRange'で他の要素を追加します。 –
ありがとうございます - それはそれを修正しました。将来あなたに迷惑をかけないように、表現木を構築するための良いリファレンスを知っていますか?私はちょうどそれの周りに私の頭を得るように見えることはできません。 –