【问题标题】:Use reflection to get lambda expression from property Name使用反射从属性 Name 获取 lambda 表达式
【发布时间】:2011-08-30 16:40:25
【问题描述】:

我想让用户选择按不同属性进行搜索。比如

[输入文本] | [选择选项 {ID、姓名、电话}] | [搜索]

我稍后会像这样构建我的查询:

repository.Where(lambda-expression)

其中 lambda-expression 是从选定的选项 {ID, NAME, PHONE} 构建的 (例如:x => x.NAME.Equals(INPUT TEXT))

有没有一种方法可以使用反射从属性名称构建 lambda?

谢谢

【问题讨论】:

    标签: c# reflection entity-framework-4 lambda


    【解决方案1】:

    您无需构建 lambda 表达式 - 您构建的是表达式树。这并不难,但需要一点耐心。在您的示例中,您可能需要:

    ParameterExpression parameter = Expression.Parameter(typeof(Foo), "x");
    Expression property = Expression.Property(parameter, propertyName);
    Expression target = Expression.Constant(inputText);
    Expression equalsMethod = Expression.Call(property, "Equals", null, target);
    Expression<Func<Foo, bool>> lambda =
       Expression.Lambda<Func<Foo, bool>>(equalsMethod, parameter); 
    

    假设:

    • 存储库元素类型为Foo
    • 您想使用名为propertyName 的属性
    • 您想与inputText 比较是否相等

    【讨论】:

    • 谢谢,它就像一个魅力...我一开始确实遇到了一个错误,我不得不将我的类型从 IEnumerable 更改为 IQueryable,但我应该一开始就使用 IQueryable。
    • @AJC: 你能把这个方法变成一个泛型方法并将它作为一个类型参数吗?或者只是将类型作为普通参数。由于您没有提供太多背景信息,因此很难知道该建议什么。
    • 是的,对不起,我在那儿有点偷懒了。我将类型作为参数传递...谢谢...
    • 我遇到了一个小问题。起初,我对该方法使用“包含”,但现在我需要一个“Equals”比较器并且我收到此错误:类型“System.String”上的多个方法“Equals”与提供的参数。。有什么想法吗?谢谢
    • @AJC:是的,使用Expression.Call 的替代重载,它采用MethodInfo 而不是string 来标识方法。
    【解决方案2】:

    对于那种事情,我使用类似这样的东西(注意:做一个“喜欢”的地方):

     public static IQueryable<TEntity> Where<TEntity>(this IQueryable<TEntity> source, string propertyName, string value) 
        {
    
            Expression<Func<TEntity, bool>> whereExpression = x => x.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, x, null).ObjectToString().IndexOf(value, StringComparison.InvariantCultureIgnoreCase) >= 0;
    
            return source.Where(whereExpression);
    
    
        }
    

    【讨论】:

    • 这个查询很有用,但是当我使用 sql profiler 检查时,它首先查询所有记录,然后在其上应用表达式。我们如何才能在一个(优化的)查询中获得包含过滤器表达式的结果?
    【解决方案3】:

    我不得不面对同样的问题,下面的方法完美地解决了我的问题。

    PropertyInfo propertyInfoObj = MyClassObject.GetType().GetProperty(PropertyName);
    repository.Where(x => propertyInfoObj.GetValue(x) == SearchValue).Select(x => propertyInfoObj.GetValue(x)).FirstOrDefault();
    

    【讨论】:

    • 您是否检查过 Sql profiler 以查看正在发出的查询?我有一种感觉,在反射代码运行之前你会发现你的整个表被加载到内存中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多