asp mvc razor 存储 lambda 表达式以列出并重用它
Posted
技术标签:
【中文标题】asp mvc razor 存储 lambda 表达式以列出并重用它【英文标题】:asp mvc razor storing lambda expression to list and reuse it 【发布时间】:2013-01-21 09:28:20 【问题描述】:我正在使用 asp.mvc 4。假设我有一个名为 Person 的模型,其中包含字段
public class Person
public int ID get; set;
public string FirstName get; set;
public string SecondName get; set;
public DateTime DateOfBirth get; set;
public DateTime DateOfWorkstart get; set;
public int NumberOfChildren get; set;
public int DepartmentID get; set;
public virtual Department Department get; set;
public class Department
public int ID get; set;
public int NameOfDepartment get; set;
在我自动生成的 razor-edit-view 字段中显示如下(为了清楚起见,我只在这篇文章中包含了重要的行)
@html.DisplayFor(modelItem => item.FirstName)
@Html.DisplayFor(modelItem => item.SecondName)
现在我想将 linq-lambda 表达式存储在一个列表中以供以后使用,我不知道该怎么做,我需要这样的东西:
@
string itemsToShow = "namepart"; // this could also be "otherpart"
List <Expression<>> list = new List();
if (itemsToShow.equals("namepart")
list.add(modelItem => item.FirstName);
list.add(modelItem => item.SecondName);
else
list.add(modelItem => item.DateOfBirth);
list.add(modelItem => item.DateOfWorkStart);
list.add(modelItem => item.NumberOfChildren);
最后我想像这样使用生成的列表
@foreach (var lambda in list)
@Html.DisplayFor(lambda)
【问题讨论】:
【参考方案1】:我会为此编写一个自定义助手:
public static class HtmlExtensions
public static IHtmlString MyHelper(this HtmlHelper<MyViewModel> html, string itemsToShow)
var sb = new StringBuilder();
if (itemsToShow == "namepart")
sb.Append(html.DisplayFor(x => x.FirstName));
sb.Append(html.DisplayFor(x => x.SecondName));
else
sb.Append(html.DisplayFor(x => x.DateOfBirth));
sb.Append(html.DisplayFor(x => x.DateOfWorkStart));
sb.Append(html.DisplayFor(x => x.NumberOfChildren));
return new HtmlString(sb.ToString());
然后简单地在视图内部:
@Html.MyHelper("namepart")
如果你想渲染另一部分:
@Html.MyHelper("otherpart")
作为替代方案,只需将此内容放入 2 个不同的局部视图中,然后:
@if (itemsToShow == "namepart")
@Html.Partial("_NamePart", Model)
else
@Html.Partial("_OtherPart", Model)
【讨论】:
感谢您的建议。是的,这看起来不错,但我的主要目标是了解如何将 lambda 表达式存储到列表中并在以后使用它; 您不能将它存储在列表中,因为您不知道 lambda 表达式的确切类型。您可以使用Expression<Func<MyViewModel, object>>
,但如果您尝试将它与模型上的值类型属性(例如 DateTime 或整数)一起使用,这将不适用于 ASP.NET MVC 帮助程序(例如 DisplayFor
)【参考方案2】:
我的大脑有一点进步。感谢您的建议。正如@darin-dimitrov 所说,秘诀是存储一个表达式树。我更新了我的第一篇文章并添加了一个相关表格。 此示例仅适用于模型已从数据库表中获取“1 单行”(例如在编辑视图中)时;
// first a small helper, which creates the member and checks nullable fields
public static Expression getExpressionPart(ParameterExpression param,
String s1, String s2)
Expression member = null;
if (s2 == null)
member = Expression.Property(param, s1);
else
// the second string is to deal with foreign keys/related data
member = Expression.PropertyOrField(
Expression.PropertyOrField(param, s1), s2
);
Type typeIfNullable = Nullable.GetUnderlyingType(member.Type);
if (typeIfNullable != null)
member = Expression.Call(member, "GetValueOrDefault", Type.EmptyTypes);
现在创建列表和表达式
List<Expression<Func<Person, object>>> list =
new List<Expression<Func<Person, object>>>();
ParameterExpression param = Expression.Parameter(typeof(Person), "p");
// maps to expression p => p.FirstName
Expression member = getExpressionPart(param, "Firstname", null);
list.Add(Expression.Lambda<Func<Person, object>>(member, param));
// maps to expression p => p.Department.NameOfDepartment
member = getExpressionPart(param, "Department", "NameOfDepartment");
list.Add(Expression.Lambda<Func<Person, object>>(member, param));
现在它可以工作了!
@foreach (var lambda in list)
@Html.DisplayNameFor(lambda)
@Html.DisplayFor(lambda)
【讨论】:
【参考方案3】:您是否尝试过这样存储 lambda:
Func<Person,bool> personExpression = (u => u.FirstName == firstname);
@Html.DisplayFor(personExpression)
对于 2 种输入类型,您的代码将如下所示:
Func<Person,Ticket,bool> personExpression =
((u,t) => u.FirstName == firstname && u.SecondName == t.SecondName);
【讨论】:
谢谢,但这不起作用。这会导致编译错误。你用这种方法成功了吗? 是的,它在控制台解决方案中运行良好。我认为 Razor 不支持它,或者?【参考方案4】:要在剃刀视图中循环遍历模型属性,您应该使用ViewData.ModelMetadata.Properties
,如this answer。例如:
@* Loop through properties. *@
@foreach (var property in ViewData.ModelMetadata.Properties)
@Html.Display(property.PropertyName)
【讨论】:
以上是关于asp mvc razor 存储 lambda 表达式以列出并重用它的主要内容,如果未能解决你的问题,请参考以下文章