9

我正在尝试编写一个通用(意味着在许多地方都很有用)控件,我可以在整个公司中重用它。

我的视图和视图模型中的实际 C# 泛型存在问题。

这是我正在尝试做的一个例子:

通用局部视图:( _Control.cshtml)

@model SimpleExample<dynamic> 

@Model.HtmlTemplate(Model.Data)

查看数据:( SimpleExample.cs)

public class SimpleExample<T>
{
    public T Data;
    public Func<T, System.Web.WebPages.HelperResult> HtmlTemplate;
}

示例用法:( FullView.cshtml)

@model Foo.MyViewData

@Html.Partial("_Control", new SimpleExample<MyViewData>
{
    Data = Model,
    HtmlTemplate = @<div>@item.SomeProperty</div>
})

我正在寻找的功能的重要部分是消费者在编写其 Html 内联时会获得一个类型化的对象,以便他们可以使用 Intellisense(如参考资料中所示FullView.cshtml)。

一切都编译得很好并且智能感知正在工作,但我在运行时收到错误:

The model item passed into the dictionary is of type 
'AnytimeHealth.Web.ViewData.SimpleExample`1[Foo.MyViewData]', 
but this dictionary requires a model item of type 
'AnytimeHealth.Web.ViewData.SimpleExample`1[System.Object]'.

我读过我可能可以在我的泛型类型上使用协方差来让它工作,但我不知道该怎么做。

你能指导我如何让这个工作吗?

4

2 回答 2

5

更改定义_Control.cshtml

@model SimpleExample<dynamic>@model dynamic.

它会起作用,但会失去 的智能感知SimpleExample,智能感知MyViewData仍然会起作用。

我认为这是因为动态类型将在运行时已知,但泛型的类型

需要一个早期的时间(也许是编译时间),那时,只有object知道。

于 2013-07-03T06:29:21.733 回答
3

您可以使用通用对象,然后使用反射渲染该对象的属性(使用帮助程序列出属性)。这与 Twitter Bootstrap 用于 MVC 4 的方法相同(为方便起见,已复制了这段代码的其中一部分): http: //nuget.org/packages/twitter.bootstrap.mvc4

_Control.cshtml

@model Object
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>@Model.GetLabel()</legend>
        @foreach (var property in Model.VisibleProperties())
        {
            using(Html.ControlGroupFor(property.Name)){
                @Html.Label(property.Name)
                @Html.Editor(property.Name)
                @Html.ValidationMessage(property.Name, null)
            }
        }
        <button type="submit">Submit</button>
    </fieldset>
}

助手.cs

public static string GetLabel(this PropertyInfo propertyInfo)
{
    var meta = ModelMetadataProviders.Current.GetMetadataForProperty(null, propertyInfo.DeclaringType, propertyInfo.Name);
    return meta.GetDisplayName();
}

public static PropertyInfo[] VisibleProperties(this IEnumerable Model)
{
    var elementType = Model.GetType().GetElementType();
    if (elementType == null)
    {
        elementType = Model.GetType().GetGenericArguments()[0];
    }
    return elementType.GetProperties().Where(info => info.Name != elementType.IdentifierPropertyName()).ToArray();
}

public static PropertyInfo[] VisibleProperties(this Object model)
{
    return model.GetType().GetProperties().Where(info => info.Name != model.IdentifierPropertyName()).ToArray();
}
于 2013-07-03T08:03:22.033 回答