2013-04-10 14 views
5

は、私はこのようないくつかの一般的な検索方法記述する必要があります。C#ジェネリックのLINQクエリ

public List<T> Search<T>(SearchParamsBase searchParams) 
{ 
    using (var context = new TestEntities()) 
    { 
     var dataType = TypeMap.Get(typeof (T)); 
     var dataSet = context.Set(dataType); 

     var searchQuery = CreateQuery((IEnumerable<object>) dataSet), searchParams) 

     return searchQuery.ToList() 
    } 
} 

を、私はIEnumerableオブジェクトをフィルタ処理する必要がある関数CreateQuery()を持っています。 この機能は、すべてのクラスで異なります。例:

CreateQuery(IEnumerable<object> collection, SearchParamsBase searchParams) 
{ 
    var search = (SomeSearchImplementation)searchParams; 
    // filter 
    collection = collection.Where(x => x.Name == search.Name); 
    // select page 
    collection = collection.Skip(search.Page * search.CountPerPage); 
    collection = collection.Take(search.CountPerPage); 
    // order by and so on 
    // ... 
    return collection; 
} 

このアイデアは正しく実装できますか?

答えて

7

基本的にここでやりたいことは、LINQクエリを動的に構築することです。これを行うには、実行時に式ツリーを変更/構築する必要があります。あなたが式ツリーと、私はこの記事と「参照」セクションで参照されたページをお勧めしますExpression<T>タイプに精通していない場合:

http://msdn.microsoft.com/en-us/library/bb397951.aspx

あなたは今、基本的な考え方のことを、のは、ダイナミックソートを実装してみましょう。以下の方法は、IQueryable<T>の拡張であり、リストだけでなくすべてのLINQデータソースに適用されるため、データベースに対して直接使用することもできます(ページングとソートについてはメモリ操作よりも効率的です) 。

dataSet.OrderByDynamic("Name", false) 
ascendingために、プロパティ Nameによってデータセットを注文する

public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string sortColumn, bool descending) 
{ 
    // Dynamically creates a call like this: query.OrderBy(p => p.SortColumn) 
    var parameter = Expression.Parameter(typeof(T), "p"); 

    string command = "OrderBy"; 

    if (descending) 
    { 
     command = "OrderByDescending"; 
    } 

    Expression resultExpression = null;  

    var property = typeof(T).GetProperty(sortColumn); 
    // this is the part p.SortColumn 
    var propertyAccess = Expression.MakeMemberAccess(parameter, property); 

    // this is the part p => p.SortColumn 
    var orderByExpression = Expression.Lambda(propertyAccess, parameter); 

    // finally, call the "OrderBy"/"OrderByDescending" method with the order by lamba expression 
    resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { typeof(T), property.PropertyType }, 
     query.Expression, Expression.Quote(orderByExpression)); 

    return query.Provider.CreateQuery<T>(resultExpression); 
} 

は今、あなたはこのコードを書くことができます。この方法は、あなたがで注文したいプロパティ名とソート方向(昇順/降順)を取り

動的フィルタリングの拡張方法を作成するのと同じパターンに従います。上記のコードを理解していれば、問題はありません。