3

我编写了一个 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));
        }
    }

阿马尔

4

1 回答 1

1

也许您可以考虑创建一个类似于Nullable<T>包含您的实体的自定义结构?Nullable<T>将 T 限制为一个结构,这就是为什么您必须创建自己的结构。这样,您可以检查 HasValue 属性,而不是检查 null 并且不知道类型时遇到问题。

于 2010-01-07T15:51:59.297 回答