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),@(item.Pet)
}
|
其原因是C#的编译器总是将匿名类型编译成internal的,当通过dynamic访问在当前上下文不可见的成员的时候,就会引发异常。问题重现:
代码如下 |
复制代码 |
using System;
using System.Collections.Generic;
using System.Linq;
namespace Controller
{
public class Test
{
///
/// 模拟匿名对象匿名类
///
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>
@foreach(var item in Model)
{
@(item.Item1),@(item.Item2)
}
|