2011-08-08 1 views
1

기본 유형 (예 : IPerson 인터페이스)의 모음에 대해 동적 LINQ 쿼리를 실행하지만 구현 고유 속성 (예 : Age와 같은)에 액세스하려면 어떻게해야합니까?유형별 속성에 액세스하는 동안 기본 유형 모음에 대한 동적 Linq 쿼리

컬렉션의 모든 항목이 동일 할 수 있습니다. 즉, 다른 항목이 동일하다고 가정 할 수있는 첫 번째 유형을 볼 수 있습니다.

다른 컬렉션에 필터를 적용 할 수있는 UI에이 속성이 필요하므로 사용자는 사용 가능한 모든 속성을 볼 수 있습니다.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Linq.Dynamic; 
using DynamicExpression = System.Linq.Dynamic.DynamicExpression; 

namespace DynamicLinqTest 
{ 
    public interface IPerson 
    { 
     string Name { get; set; } 
    } 
    public class Person : IPerson 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
     public double Income { get; set; } 
    } 

    class Program 
    { 
     public static IEnumerable<Person> GetPersons() 
     { 
      yield return new Person { Name = "Sam", Age = 26, Income = 50000 }; 
      yield return new Person { Name = "Rick", Age = 27, Income = 0 }; 
      yield return new Person { Name = "Joe", Age = 45, Income = 35000 }; 
      yield return new Person { Name = "Bill", Age = 31, Income = 40000 }; 
      yield return new Person { Name = "Fred", Age = 56, Income = 155000 }; 
     } 

     static void Main(string[] args) 
     { 
      IEnumerable<IPerson> persons = GetPersons(); 
      var personsQueriable = persons.AsQueryable(); 

      //what I would like to do: 
      // personsQueriable.Where("Age > 30"); 

      var l = DynamicExpression.ParseLambda(persons.First().GetType(), typeof(bool), "Age > 30"); 
      var filtered = personsQueriable.Provider.CreateQuery(
       Expression.Call(
        typeof(Queryable), "Where", 
        new Type[] { persons.First().GetType() }, 
        personsQueriable.Expression, Expression.Quote(l))); 

      ObjectDumper.Write(filtered); 
      Console.Read(); 
     } 
    } 
} 

답변

2

다음과 같은 코드를 생성하는 :

persons.Where((Person p) => p.Age > 30) 

persons

이 유형 인을 여기에

는 내가하고 싶은 무엇의 예는 Expression.Call 방법은 예외를 throw IEnumerable<IPerson>이며, 이는 IEnumerable<Person>으로 캐스팅 할 수 없습니다.

persons.Cast<Person>().Where(p => p.Age > 30) 

다음 코드를 사용하여 : : 그러나

var castedQueryable = personsQueriable.Provider.CreateQuery(
    Expression.Call(
     typeof(Queryable), "Cast", 
     new Type[] { persons.First().GetType() }, 
     personsQueriable.Expression)); 

var l = DynamicExpression.ParseLambda(persons.First().GetType(), typeof(bool), "Age > 30"); 
var filtered = personsQueriable.Provider.CreateQuery(
    Expression.Call(
     typeof(Queryable), "Where", 
     new Type[] { persons.First().GetType() }, 
     castedQueryable.Expression, Expression.Quote(l))); 

을, 당신은 네 번 persons을 열거하는 사실에있어 유의 당신이 원하는 것은 PersonIPerson 객체를 캐스팅 Queryable.Cast에 대한 호출을 추가하는 것입니다 이리. 목록에서 오는 경우 많은 영향을 미치지 않습니다. 원래 열거 형이 데이터베이스 쿼리에서 오는 경우에는 한 번만 열거해야합니다. 목록에서 결과를 가져온 다음 First 호출 및 표현식이 모두 적용되었는지 확인하십시오.

+0

달콤한 해결책! 나는 그 선로에도 올라 탔다. 그러나 나는 그것을하는 법을 모르고 있었다. 정말 고마워! 여러 열거 형 문제에 대해 알고 있었으므로 가능한 한 간단하게 예제를 작성했습니다. – lukebuehler