어떻게하면 일반 객체와 비교되는 Linq 표현 트리를 만들 수 있습니까?

c# entity-framework expression-trees generics linq

문제

나는 IQueryable과 T 형의 객체를 가지고있다.

IQueryable ()을하고 싶습니다. 어디에서 (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));
}

Fyi, GetProperty는 유효한 함수가 아닙니다. 나는이 기능을 수행 할 무언가가 필요하다.

나는 금요일 오후 뇌가 녹아 내리거나 복잡한 일을 할 것인가?


objectOfTypeT 다음을 할 수 있습니다 ...

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

어느 것이 완벽하게 작동하는지, 이제는 두 번째 부분 만 필요합니다.

SomeIQueryable (). 여기서 (o => o.GetProperty (fieldName) == matchValue);

수락 된 답변

이렇게 :

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

나는, 표현 주제의 수를 포함 블로그 시작했습니다 여기를 .

문제가 생기면 다른 옵션은 objectOfTypeT 먼저 리플렉션을 사용하여 값을 추출한 다음 Expression.Constant 에서 해당 값을 사용하는 것입니다.하지만 "괜찮은"것으로 판단됩니다.


인기 답변

는 어때:

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

이것은 동적 쿼리를 사용하지 않고 문자열로 속성 값을 가져 오는 방법입니다. 단점은 al 값이 boxed / unboxed 일 것입니다.



Related

아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.