호출

2012-03-19 1 views
3

나는 현재 내 개체의 EmailAddress 재산에 필요한 메소드를 호출 할 수 있도록 다음과 같은 코드를 가지고, 그것은 잘 작동 :호출

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

이것은 완벽하게 작동했습니다. 정말 고마워요. 또한 필드, 속성 및 메서드를 허용하도록 일반화 해 주셔서 감사합니다. 프로세스를 훨씬 명확하게 이해하여 이해할 수있게되었습니다. –