2013-07-03 76 views
9

我想寫一個通用的(在許多地方有用)控制,我可以在我的公司重複使用。如何在Asp.Net MVC Razor中創建'通用'控件?

我在我的視圖和viewmodel中遇到了實際的C#泛型問題。

這裏是什麼,我試圖做一個例子:

通用局部視圖:(_Control.cshtml

@model SimpleExample<dynamic> 

@Model.HtmlTemplate(Model.Data) 

的ViewData:(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]'. 

我讀過,我也許可以用我的泛型類型的協變性得到這個工作,但我不知道該怎麼做。

請問我可以如何讓這項工作?

回答

3

更改在_Control.cshtml定義:

更改此@model SimpleExample<dynamic>

@model dynamic,它會工作,但會失去SimpleExample

MyViewData智能感知將仍然有效的智能感知。

我想這是因爲動態類型將在運行時知道,但仿製藥

的類型需要一個較早的時間(也許是編譯時),在這一點上,只有object是已知的。

+0

這對我有用,除了我在_Control'中失去智能感知:(' – jjnguy

3

您可以使用通用對象,然後使用反射渲染此對象的屬性(使用助手列出屬性)。這是通過Twitter的引導爲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> 
} 

Helper.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(); 
} 
相關問題