c# - 如何创建具有多个方法调用的 ExpressionTree

标签 c# reflection expression-trees

我目前有以下代码,它允许我调用对象的 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); 

我做了几次尝试,但都以各种错误告终。我觉得我在如何创建 ExpressionTrees 的逻辑中遗漏了一些东西,对此提供一些帮助将不胜感激。

谢谢

最佳答案

这对你有好处吗?

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);

关于c# - 如何创建具有多个方法调用的 ExpressionTree,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9777241/

相关文章:

go - 使用 reflect 模拟 struct.field

c# - 使一个类的一个实例等于另一个。 – 如何取消?

c# - 从 XAML/Slider 模板获取 slider 的拇指位置

c# - 内容中的 RestSharp Json 而不是数据中的

c# - Unity 容器构建失败

c# - 通过 Emit(Opcodes.Call, methodinfo) 创建一个类型的实例

c# - LINQ 表达式树是专有树吗?

c# - 表达式树 - 在外部 lambda 中编译内部 lambda - 作用域解析

c# - 在 asp.net 中使用最小起订量测试服务类

C# 编译器错误?用于 Expression 中只写属性的对象初始值设定项语法使 csc 崩溃