c# - Razor 中的 Html.DisplayNameFor List 与 IEnumerable
问题描述
我正在实现教程中的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)
区别在于,在第一次调用表达式 cast model 时CustomerDisplayViewModel
,第二次调用是 a 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);
}
谢谢。
解决方案
发生这种情况是因为的泛型参数TModel
不是covariant。基本上,你不能这样做:IHtmlHelper
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
)。
推荐阅读
- javascript - 相同的两个页面之一有“unexpected token <”错误,而另一个工作完全正确
- c# - 我使用了错误的数据网格吗?
- azure-active-directory - Azure AD 并使用 IAM 和个人配置文件连接到 AWS RDS
- c++ - 从其他程序运行时如何重定向输出?
- python - python中的负正则表达式模式匹配
- java - HTMLworker 正在生成的 pdf 顶部打印样式标记内容
- reactjs - 如何在 React JS 中的 .map 中放置条件 IF ELSE
- rust - 为什么不能将 &str 传递给接受 &dyn 显示特征对象的函数?
- angular - 当原点拖动方向改变时获取坐标
- spring-retry - 需要同时使用 SimpleRetryPolicy 和 TimeoutRetryPolicy,这样我就可以为重试模板设置最大尝试和超时