【问题标题】:How do I build a Linq Expression Tree that compares against a generic object?如何构建与通用对象进行比较的 Linq 表达式树?
【发布时间】:2010-09-18 22:21:20
【问题描述】:

我有一个 IQueryable 和一个 T 类型的对象。

我想做 IQueryable().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName))

所以...

public IQueryable<T> DoWork<T>(string fieldName)
        where T : EntityObject
{
   ...
   T objectOfTypeT = ...;
   ....
   return SomeIQueryable<T>().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName));
}

仅供参考,GetProperty 不是有效函数。我需要执行此功能的东西。

我是周五下午的大脑融化了还是这是一件复杂的事情?


objectOfTypeT 我可以做以下...

var matchToValue = Expression.Lambda(ParameterExpression
.Property(ParameterExpression.Constant(item), "CustomerKey"))
.Compile().DynamicInvoke();

效果很好,现在我只需要第二部分:

return SomeIQueryable().Where(o => o.GetProperty(fieldName) == matchValue);

【问题讨论】:

    标签: c# linq entity-framework generics expression-trees


    【解决方案1】:

    像这样:

        var param = Expression.Parameter(typeof(T), "o");
        var fixedItem = Expression.Constant(objectOfTypeT, typeof(T));
        var body = Expression.Equal(
            Expression.PropertyOrField(param, fieldName),
            Expression.PropertyOrField(fixedItem, fieldName));
        var lambda = Expression.Lambda<Func<T,bool>>(body,param);
        return source.Where(lambda);
    

    我已经创建了一个博客,它将涵盖许多表达主题,here

    如果遇到任何问题,另一种选择是先从objectOfTypeT 中提取值(使用反射),然后在Expression.Constant 中使用该值,但我怀疑“原样”会很好。

    【讨论】:

    • 完美。正是我需要的。现在要弄清楚到底发生了什么:)
    【解决方案2】:

    据我目前所见,它必须是......

    IQueryable<T>().Where(t => 
    MemberExpression.Property(MemberExpression.Constant(t), fieldName) == 
    ParameterExpression.Property(ParameterExpression.Constant(item), fieldName));
    

    虽然我可以编译它,但它并没有完全按照所需的方式执行。

    【讨论】:

    • 关闭;您需要构建一个 LambdaExpression - 请参阅我的帖子。
    【解决方案3】:

    怎么样:

        public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
    
        }
    
        public Func<T, TRes> GetPropertyFunc<T, TRes>(string propertyName)
        {
            // get the propertyinfo of that property.
            PropertyInfo propInfo = typeof(T).GetProperty(propertyName);
    
            // reference the propertyinfo to get the value directly.
            return (obj) => { return (TRes)propInfo.GetValue(obj, null); };
        }
    
        public void Run()
        {
            List<Person> personList = new List<Person>();
    
            // fill with some data
            personList.Add(new Person { Name = "John", Age = 45 });
            personList.Add(new Person { Name = "Michael", Age = 31 });
            personList.Add(new Person { Name = "Rose", Age = 63 });
    
            // create a lookup functions  (should be executed ones)
            Func<Person, string> GetNameValue = GetPropertyFunc<Person, string>("Name");
            Func<Person, int> GetAgeValue = GetPropertyFunc<Person, int>("Age");
    
    
            // filter the list on name
            IEnumerable<Person> filteredOnName = personList.Where(item => GetNameValue(item) == "Michael");
            // filter the list on age > 35
            IEnumerable<Person> filteredOnAge = personList.Where(item => GetAgeValue(item) > 35);
        }
    

    这是一种无需使用动态查询即可通过字符串获取属性值的方法。缺点是所有值都将被装箱/取消装箱。

    【讨论】:

      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多