2012-03-20 66 views
2

我正在使用下面的代碼來執行方法。它的工作原理爲string標準方法,例如StartsWith,但是我試圖用幾個字符串擴展方法,包括Contains一個覆蓋該alllows爲不區分大小寫:如何使用反射調用具有參數的非通用靜態擴展方法

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.

我該如何解決這個問題?

僅供參考,這裏是Contains擴展:

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

感謝


編輯

更新爲每鮑拉的答案,雖然我現在得到以下錯誤:

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

你必須通過null ConsantExpression作爲Expression.Call實例參數,並添加mc第一個參數。

+0

我試過這個雖然仍然收到一個錯誤 - 我用完整的方法更新了我的OP。非常感謝您的幫助,這再次巴拉茲:) – 2012-03-20 12:14:26

+0

您的列表應該是一個'列表'。首先添加'm',然後用'AddRange'添加其他元素。 – 2012-03-20 12:20:09

+0

謝謝 - 已修復它。爲了節省我以後再次困擾你,你是否知道建立表達樹的任何好的參考。我似乎無法擺脫困境。 – 2012-03-20 12:27:34

相關問題