2012-03-19 51 views
3

目前,我有下面的代碼,讓我打電話給我的對象的EmailAddress財產所需的任何方法,並且它的偉大工程:現在如何創建具有多個方法的ExpressionTree調用

public static Expression<Func<T, bool>> BuildEmailAddressLambda(string method, params object[] args) { 
    var e = Expression.Parameter(typeof(T), "e"); 
    var propertyInfo = typeof(T).GetProperty("EmailAddress"); 
    var m = Expression.MakeMemberAccess(e, propertyInfo); 
    var mi = m.Type.GetMethod(method, args.Select(a => a.GetType()).ToArray()); 
    var c = args.Select(a => Expression.Constant(a, a.GetType())).ToArray(); 

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

// called: 
lambda = LambdaExpressionHelper<MailingListMember>.BuildEmailAddressLambda("StartsWith", "r", StringComparison.OrdinalIgnoreCase); 

然而,我需要修改代碼,使其適用於除EmailAddress以外的我的對象的成員。具體而言,我想建立一個樹,以覆蓋下面的表達式,其中使用多個方法調用:

e.GetStringValue(12).StartsWith("r", StringComparison.OrdinalIgnoreCase); 

我已進行了多種嘗試,所有這些在各種錯誤結束。我覺得我在創建ExpressionTree的邏輯中缺少一些東西,對此有一些幫助將不勝感激。

謝謝

回答

3

這對你有好處嗎?

public static Expression<Func<T, bool>> BuildEmailAddressLambda<T>(
    string member, IEnumerable<object> memberArgs, string method, params object[] args) 
{ 
    var e = Expression.Parameter(typeof(T), "e"); 
    var memberInfo = 
     (MemberInfo) typeof(T).GetField(member) ?? 
     (MemberInfo) typeof(T).GetProperty(member) ?? 
     (MemberInfo) typeof(T).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())); 

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

// called: 
lambda = LambdaExpressionHelper<MailingListMember>.BuildEmailAddressLambda("EmailAddress", null, "StartsWith", "r", StringComparison.OrdinalIgnoreCase); 
// or 
lambda = LambdaExpressionHelper<MailingListMember>.BuildEmailAddressLambda("GetStringValue", new object[] { 12 }, "StartsWith", "r", StringComparison.OrdinalIgnoreCase); 
+0

這工作完美 - 非常感謝你。另外,感謝你使它成爲通用的,以便它允許字段,屬性和方法,這使得我的理解過程更加清晰。 – 2012-03-20 09:41:56

相關問題