簡體   English   中英

Html.DisplayNameFor List vs IEnumerable in Razor

[英]Html.DisplayNameFor List vs IEnumerable in Razor

我正在實現教程中的PaginatedList

有用。 如果我在我的 Razor 頁面@model定義為IEnumerable我可以這樣做:

@model IEnumerable<CustomerDisplayViewModel>
@Html.DisplayNameFor(model => model.LastName)

如果我將@model定義為List ,則@Html.DisplayNameFor助手的工作方式不同,我必須這樣稱呼它:

@model List<CustomerDisplayViewModel>
@Html.DisplayNameFor(model => model.First().LastName)

不同之處在於,在第一次調用中,表達式將 model 轉換為CustomerDisplayViewModel而在第二次調用中它是List<CustomerDisplayViewModel>

該問題是由編譯器傾向於將調用轉換為

Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> 
string DisplayNameFor<TResult>(Expression<Func<TModel, TResult>> expression);

代替

Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperDisplayNameExtensions
public static string DisplayNameFor<TModelItem, TResult>(
this IHtmlHelper<IEnumerable<TModelItem>> htmlHelper, Expression<Func<TModelItem, TResult>> expression);

我知道我可以使用我的解決方法( @Html.DisplayNameFor( model => model.First().LastName) ),但感覺不正確。

有沒有辦法進行調用或者生成我自己的調用 IEnumerable 擴展的擴展(我不希望從頭開始創建擴展,這個調用應該與 IEnumerable 完全一樣)。 我可以使用 List<> 創建擴展方法,但是我無法轉換它。

 public static string DisplayNameFor<TModelItem, TResult>
            (this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<List<TModelItem>> htmlHelper,
            Expression<Func<TModelItem, TResult>> expression)
        {
            var castHelper = --- somehow cast helper to IHtmlHelper<IEnumerable<TModelItem>
            return castHelper.DisplayNameFor(expression);
        }

謝謝。

發生這種情況是因為IHtmlHelper的泛型參數TModel不是covariant 基本上,你不能這樣做:

IHtmlHelper<List<CustomerDisplayViewModel>> helperList = new HtmlHelper<List<CustomerDisplayViewModel>(...);

IHtmlHelper<IEnumerable<CustomerDisplayViewModel>> helperIEnumerable = helperList;
// the above line is an error

但是,您可以使用IEnumerable<T>來做到這一點:

IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList; // no error

這是因為IEnumerable是這樣聲明的:

public interface IEnumerable<out T> : IEnumerable { .. }

注意out關鍵字,它指定泛型參數T是協變的。 如果IHtmlHelper<TModel>在框架中這樣聲明:

interface IHtmlHelper<out TModel> { .. }

你的代碼會起作用的。


盡管如此,在這種情況下,您仍然可以使用Html.DisplayNameForInnerType()來獲取顯示名稱(僅限 ASP.NET Core):

@model PaginatedList<CustomerDisplayViewModel>
...
@Html.DisplayNameForInnerType((CustomerDisplayViewModel c) => c.LastName)

請注意,您必須明確指定 lambda 表達式參數的類型。( CustomerDisplayViewModel c )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM