ASP.NET MVC3 + Entity Framework項目中,從控制器傳遞匿名對象到視圖非常常見,原本以為用dynamic能輕鬆搞定,最後發現我錯了:
Controller:
| 代碼如下 |
複製代碼 |
public ActionResult Index() { testContext context = new testContext(); dynamic data = context.People .Join(context.Pets, person => person.Id, Pet => Pet.Pid, (person, pet) => new { Person = person.Name, Pet = pet.Name }); return View(data); }
View: @model dynamic
@foreach(var item in Model) { @(item.Person)<text>,</text>@(item.Pet)<br /> } |
其原因是C#的編譯器總是將匿名型別編譯成internal的,當通過dynamic訪問在當前上下文不可見的成員的時候,就會引發異常。問題重現:
| 代碼如下 |
複製代碼 |
using System; using System.Collections.Generic; using System.Linq; namespace Controller { public class Test { /// <summary> /// 類比匿名對象匿名類 /// </summary> private class Anonymous { public string Person { get; set; } public string Pet { get; set; } } public dynamic GetValue() { return new Anonymous(); } } } namespace View { using Controller; class Program { static void Main(string[] args) { dynamic anonymous = new Test().GetValue(); Console.WriteLine(anonymous.Person); Console.ReadKey(); } } } |
以前都用老趙的ToDynamic方法解決,今天在.NET 4.0的System命名空間下看到一個類Tuple,瞭解後發現用它也可以解決上邊的問題:
Controller:
| 代碼如下 |
複製代碼 |
public ActionResult Index() { testContext context = new testContext(); dynamic data = context.People .Join(context.Pets, person => person.Id, Pet => Pet.Pid, (person, pet) => new { Person = person.Name, Pet = pet.Name }) .ToList().Select(item => Tuple.Create(item.Person, item.Pet)); return View(data); } View: @model IEnumerable<Tuple<string, string>>
@foreach(var item in Model) { @(item.Item1)<text>,</text>@(item.Item2)<br /> } |