我有一个 MVC3 站点,我已经设置它来测试另一个站点 - 其中大部分都快速而肮脏,所以我没有去城镇为所有 View 创建模型和 View 模型类型 - 仅在需要输入的地方用户。
好的,所以我有一个 Controller 方法,它可以投影 Linq 序列并将其设置为 ViewBag
.
ViewBag.SomeData = Enumerable.Range(1,10).Select(i=> new { Value = i });
在我看来(Razor C#)然后我想读这个 - 很简单:
@foreach(dynamic item in ViewBag.SomeData)
{
@:Number: @item.i
}
当然,除了我得到一个
RuntimeBinderException
因为在 Controller 中创建的匿名类型在 Web 项目的输出程序集内部,并且此处的实际 Razor 代码将在构建管理器生成的不同程序集中运行,所以总而言之 拒绝! 显然,“适当的”模型类型可以解决问题——但假设我只是不想这样做,因为这是我的特权(!)——如何最好地将代码保持在最低限度并保持动态性?
最佳答案
好的,抱歉,我只是不同意这太可怕了等等。是的,我永远不会考虑在生产站点上做这些事情-但对于原型(prototype)设计、非商业性、仅限内部、测试目的,我认为使用这个方法是完全有效的。
这就是我所做的(我强调这只是真正充分解决了匿名类型的问题);将成员抬出并插入 ExpandoObject
.
我最初的更改是使投影成为返回 ExpandoObject
的多语句。 :
ViewBag.SomeData = Enumerable.Range(1,10).Select(i=> {
var toReturn = new ExpandoObject();
toReturn.Value = i;
return toReturn;
});
这几乎和匿名类型一样短,只是不那么干净。
但后来我想知道我是否可以从匿名类型中获取公开可读的成员(可能依赖于编译器内部 - 类型是内部的,但它生成的属性是公共(public)的):
public static class SO7429957
{
public static dynamic ToSafeDynamic(this object obj)
{
//would be nice to restrict to anonymous types - but alas no.
IDictionary<string, object> toReturn = new ExpandoObject();
foreach (var prop in obj.GetType().GetProperties(
BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead))
{
toReturn[prop.Name] = prop.GetValue(obj, null);
}
return toReturn;
}
}
这意味着我可以使用我的原始代码 - 但在最后标记了一个小扩展方法调用:
ViewBag.SomeData=Enumerable.Range(1,10).Select(i=> new { Value = i }.ToSafeDynamic());
你知道吗 - 我知道它效率不高,大多数人会说它很丑;但它会节省我的时间,让我可以专注于在我的测试站点中编写功能,以便我的 QA 团队用于测试真实的东西(其代码当然是完美无瑕的 :))。
关于.net - 匿名类型缺少成员问题的动态 View - MVC3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7429957/