创造一个参数等于对象的LINQ表达 [英] Creating a LINQ Expression where parameter equals object

查看:134
本文介绍了创造一个参数等于对象的LINQ表达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于原始值年龄我知道如何创建这样的表达式:

Given a primitive value age I know how to create an expression like this:

//assuming: age is an int or some other primitive type
employee => employee.Age == age



这样做:

By doing this:

var entityType = typeof(Employee);
var propertyName = "Age";
int age = 30;
var parameter = Expression.Parameter(entityType, "entity");

var lambda = Expression.Lambda(
        Expression.Equal(
            Expression.Property(parameter, propertyName),
            Expression.Constant(age)
        )                    
    , parameter);



除了在场景中有关财产和不断的是原始类型的正常工作。

That works fine except in scenarios where the property and constant in question are primitive types.

我将如何构建一个类似的表达如果比较对象之间

How would I construct a similar expression if the comparison is between objects?

使用EF我可以只写:

Location location = GetCurrentLocation();
employees = DataContext.Employees.Where(e => e.Location == location);



这也适用,但如果我尝试创建相同的表达式:

That also works, but if I try to create the same expression:

var entityType = typeof(Employee);
var propertyName = "Location";
var location = GetCurrentLocation();
var parameter = Expression.Parameter(entityType, "entity");

var lambda = Expression.Lambda(
        Expression.Equal(
            Expression.Property(parameter, propertyName),
            Expression.Constant(location)
        )                    
    , parameter);



我得到一个错误,指出:

I get an error that says:

无法创建类型位置的恒定值。只有基本类型或枚举类型在这方面的支持。

我怀疑是 Expression.Constant()只希望基本类型,所以我需要使用不同的表达工厂方法。 (maype Expression.Object - 我知道,不存在)

My suspicion is that Expression.Constant() only expects primitive types, so I need to use a different expression factory method. (maype Expression.Object? - I know that doesn't exist)

有没有一种方法来创建一个表达式比较的对象?这是为什么EF能够正确解释它,如果它是一个编译的LINQ语句,但不是当它是一种表达?

Is there a way to create an expression that compares objects? Why is that EF is able to interpret it correctly if its a compiled LINQ statement, but not when it is an expression?

推荐答案

除了什么在以前的答案被提及。更具体的解决方案会去这样的:

In addition to what has been mentioned in previous answers. A more specific solution would go as such:

public static Expression CreateExpression<T>(string propertyName, object valueToCompare)
{
    // get the type of entity
    var entityType = typeof(T);
    // get the type of the value object
    var valueType = valueToCompare.GetType();
    var entityProperty = entityType.GetProperty(propertyName);
    var propertyType = entityProperty.PropertyType;


    // Expression: "entity"
    var parameter = Expression.Parameter(entityType, "entity");

    // check if the property type is a value type
    // only value types work 
    if (propertyType.IsValueType || propertyType.Equals(typeof(string)))
    {
        // Expression: entity.Property == value
        return Expression.Equal(
            Expression.Property(parameter, otherProperty),
            Expression.Constant(valueToCompare)
        );
    }
    // if not, then use the key
    else
    {
        // get the key property
        var keyProperty = propertyType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0);

        // Expression: entity.Property.Key == value.Key
        Expression.Equal(
            Expression.Property(
                Expression.Property(parameter, entityProperty),
                keyProperty
            ),
            Expression.Constant(
                keyProperty.GetValue(valueToCompare),
                keyProperty.PropertyType
            )
        );
    }
}



要点:


  1. 确保检查空

  2. 确保属性类型 VALUETYPE 是兼容的(无论他们是同一类型或可转换)

  3. 若干假设这里做(如你做分配 KeyAttribute

  4. 此代码没有进行测试,因此它是不完全复制/粘贴准备好了。

  1. Make sure to check for nulls
  2. Make sure propertyType and valueType are compatible (either they are the same type or are convertible)
  3. Several assumptions are made here (e.g. that you do assign a KeyAttribute)
  4. This code is not tested, so it is not exactly copy/paste ready.

希望有所帮助。

这篇关于创造一个参数等于对象的LINQ表达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆