我编写了一个 List`1 编辑器模板,用于 EditorFor 扩展方法 (MVC2),但是在使用泛型 + 空对象时遇到了问题。
给定一个模型
class MyModel {
public Foo SomeFoo { get;set; }
public List<Foo> SomeFooList { get;set; }
}
和 /Views/Shared/EditorTemplates/List`1.ascx 中的模板
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
IEnumerable enumerableModel;
if (Model != null && (enumerableModel = Model as IEnumerable) != null)
{
foreach (var v in enumerableModel)
{
var model = v;
Response.Write(Html.EditorFor(m => model));
}
}
%>
我得到了 SomeFoo 的预期编辑器,以及 SomeFooList 的任何不为空的元素,因为 ModelMetaData 中的类型将是“Foo”。但是,如果我将“null”作为 SomeFooList 中的对象之一,则我不会得到任何渲染,因为模型的类型是“object”,而不是 Foo 或更一般地 T 从我的列表的通用参数中。
本质上,我想实现类似
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<T>> where T : class" %>
所以我知道我的清单的类型。
我还可以考虑在 null 的情况下更改 ModelMetaData.ModelType 字段(通过创建一个新对象,因为这是只读的)——但这是我想避免的那些讨厌的黑客行为之一。
另一个想法是使用 .Invoke 调用 EditorFor 方法并将 typeof(T) 传递到那里,但同样,我想尽可能避免使用这种类型的代码。
有什么想法吗?
更新:
尝试将类型放入模型元数据中看起来比我最初预期的要复杂一些。我已经用以下似乎可行的方法更新了我的代码,但我仍然不太热衷于 solition:
if (Model != null && (enumerableModel = Model as IEnumerable) != null)
{
Type listType = null;
if (enumerableModel.GetType().IsGenericType)
{
listType = enumerableModel.GetType().GetGenericArguments()[0];
}
foreach (var v in enumerableModel)
{
var model = v;
if (model == null && listType != null)
model = Activator.CreateInstance(listType);
Response.Write(Html.EditorFor(m => model));
}
}
阿马尔