model是你的模型,modelitem是lambda表达式的参数
你可以将lambda当作一个函数(只是没有名字)
我们假设它的名字叫foo,Sname是string,modelitem是User,那么
model => model.Sname
就是
string foo(User modelitem)
{
return model.Sname;
}
以及
@Html.DisplayNameFor(foo)
你可以将lambda当作一个函数(只是没有名字)
我们假设它的名字叫foo,Sname是string,modelitem是User,那么
model => model.Sname
就是
string foo(User modelitem)
{
return model.Sname;
}
以及
@Html.DisplayNameFor(foo)
1.为什么foo的参数是modelitem,下面却return model.Sname,不应该是modelitem.Sname吗?
2.既然要输出的只是model.Sname,为什么不直接@Html.DisplayNameFor(model.Sname),还要绕一圈用一个匿名函数的形式?
@Html.DisplayNameFor(model.Sname)
而要写
@Html.DisplayNameFor(model => model.Sname)
这是因为Lambda表达式不同于一般的委托或者函数调用,它是以表达式树的形式被编译为代码的。你可以想象,这个表达式的每个语句,都可以在程序运行的时候被查询出来。
DisplayNameFor可以依赖这些信息,还原出Sname这个属性名,甚至它包含的Attribute,比如常用的DisplayName、Required、Length等等,根据它的显示名称、是否为必须填写的字段、允许的长度等等来格式化HTML标记。
而如果没有Lambda表达式,那么这些就要程序员手工传进去了,无疑需要很多额外的代码
1.为什么foo的参数是modelitem,下面却return model.Sname,不应该是modelitem.Sname吗?
2.既然要输出的只是model.Sname,为什么不直接@Html.DisplayNameFor(model.Sname),还要绕一圈用一个匿名函数的形式?
那是我笔误
是
string foo(User modelitem)
{
return modelitem.Sname;
}
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;namespace ConsoleApplication1
{
class User
{
public int ID { get; set; } [DisplayName("姓名")]
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
var model = new User() { ID = 1, Name = "张三" };
var mvc = new MVCHelper<User>(model);
Console.WriteLine(mvc.DisplayFor(modelitem => modelitem.ID));
Console.WriteLine(mvc.TextBoxFor(modelitem => modelitem.ID));
Console.WriteLine(mvc.DisplayFor(modelitem => modelitem.Name));
Console.WriteLine(mvc.TextBoxFor(modelitem => modelitem.Name));
}
} class MVCHelper<TModel>
{
private TModel model { get; set; } public MVCHelper(TModel m) { model = m; } public string DisplayFor<T>(Expression<Func<TModel, T>> exp)
{
string s = "";
var t = ((exp.Body) as MemberExpression).Member;
if (t.GetCustomAttributes(typeof(DisplayNameAttribute), false).Any())
{
s = (t.GetCustomAttributes(typeof(DisplayNameAttribute), false)[0] as DisplayNameAttribute).DisplayName;
}
else
{
s = t.Name;
}
return string.Format("<label for='{0}'>{1}</label>", exp.Body, s);
}
public string TextBoxFor<T>(Expression<Func<TModel, T>> exp)
{
return string.Format("<input type='textbox'>{0}</input>", exp.Compile()(model));
}
}
}
<label for='modelitem.ID'>ID</label>
<input type='textbox'>1</input>
<label for='modelitem.Name'>姓名</label>
<input type='textbox'>张三</input>
Press any key to continue . . .
你注意,它之所以用Lambda表达式,是因为只有这样,它才能检索到属性的属性名和Attribute中的DisplayName。
当然,在真实的MVC中,它的实现更为复杂,但是原理就是这样。你可以试想下,如果你不用Lambda,你有什么办法可以让调用足够简单,同时能做到相同的功能。