乍看有點奇妙的型別 IEnumerable<dynamic>,可以用來傳回匿名型別的 IEnumerable 集合,還蠻方便的。
舉例來說,我在 ASP.NET 網頁上用一個 GridView 來顯示查詢結果(可分頁、可排序)。此 GridView 繫結至一個 ObjectDataSource:
如上述標籤所示,此 ObjectDataSource 物件會使用 MyDemo.Web.CustomerPage 類別的 GetCustomers 方法來取得客戶資料。這個 GetCustomers 方法大概長這樣:
此方法的回傳型別是 IEnumerable<Models.Customer>,而且查詢結果包含 Customer 資料表的全部欄位。程式可以順利編譯、執行。
可是,如果資料表的欄位數量太多,希望改為僅選取部分欄位,而且不想定義新的 view model 類別,則原先的 LINQ 查詢敘述可能會改成:
此時的變數 qry 的型別就成了匿名的 IQueryable 集合,亦即 IQueryable<只有編譯器知道的型別>。
問題來了:既是匿名的泛型集合,此方法的回傳型別該怎麼寫呢?
試過幾種寫法,不是無法通過編譯就是執行時發生錯誤,例如轉型失敗、物件不支援分頁之類等等,最後是用 IEnumerable<dynamic> 來解決:
最後的 return 敘述,在呼叫 ToList 方法時也可以明白寫成 ToList<dynamic>()。
C# 4 的 dynamic 語法還藏有不少有趣的東西哩!
舉例來說,我在 ASP.NET 網頁上用一個 GridView 來顯示查詢結果(可分頁、可排序)。此 GridView 繫結至一個 ObjectDataSource:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetCustomers"
TypeName="MyDemo.Web.CustomerPage" >
</asp:ObjectDataSource>
如上述標籤所示,此 ObjectDataSource 物件會使用 MyDemo.Web.CustomerPage 類別的 GetCustomers 方法來取得客戶資料。這個 GetCustomers 方法大概長這樣:
public IEnumerable<Models.Customer> GetCustomers()
{
using (var db = new Models.NorthwindContext())
{
var qry = from c in db.Customer
select c;
return qry
.OrderByDescending(c => c.ID)
.ToList();
}
}
此方法的回傳型別是 IEnumerable<Models.Customer>,而且查詢結果包含 Customer 資料表的全部欄位。程式可以順利編譯、執行。
可是,如果資料表的欄位數量太多,希望改為僅選取部分欄位,而且不想定義新的 view model 類別,則原先的 LINQ 查詢敘述可能會改成:
var qry = from c in db.Customer
select new
{
ID,
CompanyName,
};
此時的變數 qry 的型別就成了匿名的 IQueryable 集合,亦即 IQueryable<只有編譯器知道的型別>。
問題來了:既是匿名的泛型集合,此方法的回傳型別該怎麼寫呢?
試過幾種寫法,不是無法通過編譯就是執行時發生錯誤,例如轉型失敗、物件不支援分頁之類等等,最後是用 IEnumerable<dynamic> 來解決:
public IEnumerable<dynamic> GetCustomers()
{
using (var db = new Models.NorthwindContext())
{
var qry = from c in db.Customer
select new
{
ID,
CompanyName,
};
return qry
.OrderByDescending(c => c.ID)
.ToList();
}
}
最後的 return 敘述,在呼叫 ToList 方法時也可以明白寫成 ToList<dynamic>()。
C# 4 的 dynamic 語法還藏有不少有趣的東西哩!
沒有留言: