2014-05-13 26 views
3

我很困難..我需要採取一個對象的平面列表,作爲字符串的幾個字段數組數組(由哪個排序,哪個選擇)在運行時提供,並以某種方式生成一個LINQ查詢以返回JSON序列化的對象。動態建立一個使用字符串字段名稱的層次結構的linq查詢?

我已經建立了一個示例repro下面的設置。 OrderBy很簡單,我只是使用GetType()。GetProperty()來查找正確的屬性,並迭代orderby字段以菊花鏈.OrderBy調用。這一切都在GroupBy上分崩離析,因爲每一個都將結果包裝在IEnumerable>中。

有沒有一種很好的方法來做到這一點?我在網上找到的所有東西都有人訴諸舊的遞歸程序代碼。 LINQ必須有辦法做到這一點,但我迷路了。一切我嘗試甚至不會編譯,類型就不會匹配..

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Text; 
using System.Threading.Tasks; 
using System.Linq.Dynamic; 

namespace linqtest2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var products = new List<Product> 
       { 
        new Product("Food", "Fruit", "Apple"), 
        new Product("Food", "Fruit", "Banana"), 
        new Product("Food", "Fruit", "Orange"), 
        new Product("Food", "Vegetables", "Carrot"), 
        new Product("Food", "Vegetables", "Pea"), 
        new Product("Drink", "Soft Drink", "Orange Juice"), 
        new Product("Drink", "Soft Drink", "Lemonade"), 
        new Product("Drink", "Alcoholic", "Bitter"), 
        new Product("Drink", "Alcoholic", "Lager"), 
        new Product("Drink", "Alcoholic", "Vodka") 
       }; 

      string[] select = new[] { "Category", "Name" }; 
      string[] orderBy = new[] { "Name", "Category" }; 
      string[] groupBy = new[] { "Category", "Subcategory" }; 
     } 
    } 

    public class Product 
    { 
     public string Name { get; set; } 
     public string Category { get; set; } 
     public string Subcategory { get; set; } 

     public Product(string category, string subcategory, string name) 
     { 
      Category = category; 
      Subcategory = subcategory; 
      Name = name; 
     } 
    } 
} 

回答

2

請檢查Dynamic Linq庫,它提供了一種使用字符串,而不是lambda表達式。

使用動態LINQ你可以這樣寫:

products.OrderBy("Category").ThenBy("Name") 

和很多其他的可能性。

編輯:

更新溶液是更加動態

IQueryable<Product> query = products; 
bool firstOrderBy = true; 
foreach(var orderExpression in orderBy) 
{ 
    if (firstOrderBy) 
    { 
     query = query.OrderBy(orderExpression); 
     firstOrderBy = false; 
    } 
    else 
    { 
     query = query.ThenBy(orderExpression); 
    } 
} 

正如我所建議的,驗證庫,探索它並根據需要進行調整。你也可以做GroupBy and 請選擇,請用它。

請檢查@dkackman提出的解決方案,看看哪種解決方案更適合您的需求,無論您需要做什麼解決方案來適應您的需求。

+0

我該如何動態執行此操作?我需要以某種方式迭代陣列,然後一次添加這些。 – XeroxDucati

+0

@XeroxDucati我更新了答案。 – LawfulHacker

2

Linq語法的確建立在編譯時知道數據的靜態結構的基礎上。與編譯時間和綁定相比,底層的System.Linq.Expressions命名空間具有創建運行時的巨大能力,但是這是一項相當費力的工作。

爲了支持輸入和輸出的動態輸入,最好使用一些庫。

@Sergio建議的動態Linq是一種選擇。

SqlLinq是另一個。使用SqlLinq,你會以字符串的形式動態構建整個查詢,並執行如下所示的操作:

var products = new List<Product> 
    { 
     new Product("Food", "Fruit", "Apple"), 
     new Product("Food", "Fruit", "Banana"), 
     new Product("Food", "Fruit", "Orange"), 
     new Product("Food", "Vegetables", "Carrot"), 
     new Product("Food", "Vegetables", "Pea"), 
     new Product("Drink", "Soft Drink", "Orange Juice"), 
     new Product("Drink", "Soft Drink", "Lemonade"), 
     new Product("Drink", "Alcoholic", "Bitter"), 
     new Product("Drink", "Alcoholic", "Lager"), 
     new Product("Drink", "Alcoholic", "Vodka") 
    }; 

var results = products.Query<Product, dynamic>("SELECT category, subcategory, count(*) AS cnt FROM this GROUP BY category, subcategory ORDER BY category, subcategory"); 

foreach(dynamic d in results) 
{ 
    Debug.WriteLine("{0} {1} {2}", (string)d.category, (string)d.subcategory, (int)d.cnt); 
} 
+0

好的,我不知道。當你發現表達樹背後的力量後,Linq將永遠不會一樣。 – LawfulHacker

相關問題