从 lambda 表达式中获取一个 属性 名称 *没有* 对象实例
Get a property name from a lambda expression *without* an object instance
Asp.net MVC 在 Html 泛型 class 上引入了 EditorFor
方法。它允许您编写简洁地标识视图模型字段的代码。在这种情况下,此代码的来源页面必须具有某种类型的视图模型,该视图模型具有 StudentId
属性 否则这将不起作用。
@Html.EditorFor(m => m.StudentId)
EditorFor
属性的签名是这样的。
EditorFor<TModel,TValue>(HtmlHelper<TModel>, Expression<Func<TModel,TValue>>)
该方法是在知道 TModel
类型的通用类型上定义的。所以 lambda 表达式可以像 m => m.StudentId
一样简单,我们都知道 m
的类型就是 TModel
的类型。在这种情况下,它是页面的视图模型。
我希望能够编写类似的代码,而不知道 属性 定义在什么类型上。我希望能够写...
@Html.EditorFor(M.StudentId) // here M is a type not a lambda parameter
@Html.EditorFor(X.Y) // here X is a type not a lambda parameter
我希望能够指定任意类型和任意参数,并使用可识别两者的内容调用该方法。例如,如果使用 PropertyInfo
调用该方法,那么我可以同时看到 属性 和定义它的类型。
换句话说...就像 nameof(X.Y)
为任意类型 X
给出字符串 "Y"
一样,我想要一个表达式,它给出类似PropertyInfo
也是。也许 property(X.Y)
并且您从类型 X
.
中取回 属性 Y
的 PropertyInfo
您可以像 EditorFor
一样使用 属性 表达式。您可以在没有实例的情况下执行此操作。
一个区别是您必须指定表达式参数的类型来告诉编译器对象类型是什么。所以而不是
EditorFor( x => x.Name ); //Specifies a property but not a type
...你的表情应该是这样的:
EditorFor( (MyType x) => x.Name ); //Specifies property and the type it belongs to
您可以使用像这样的简短方法来完成此操作:
static PropertyInfo GetPropertyInfo<TIn, TOut>(Expression<Func<TIn, TOut>> expression)
{
var memberExp = expression.Body as MemberExpression;
return memberExp?.Member as PropertyInfo;
}
然后你可以这样做:
var p1 = GetPropertyInfo((string s) => s.Length);
Console.WriteLine("{0}.{1}", p1.DeclaringType.FullName, p1.Name);
var p2 = GetPropertyInfo((DateTime d) => d.Minute);
Console.WriteLine("{0}.{1}", p2.DeclaringType.FullName, p2.Name);
var p3 = GetPropertyInfo((Stream s) => s.CanSeek);
Console.WriteLine("{0}.{1}", p3.DeclaringType.FullName, p3.Name);
输出:
System.String.Length
System.DateTime.Minute
System.IO.Stream.CanSeek
请注意,我们从来不需要任何实例。
Asp.net MVC 在 Html 泛型 class 上引入了 EditorFor
方法。它允许您编写简洁地标识视图模型字段的代码。在这种情况下,此代码的来源页面必须具有某种类型的视图模型,该视图模型具有 StudentId
属性 否则这将不起作用。
@Html.EditorFor(m => m.StudentId)
EditorFor
属性的签名是这样的。
EditorFor<TModel,TValue>(HtmlHelper<TModel>, Expression<Func<TModel,TValue>>)
该方法是在知道 TModel
类型的通用类型上定义的。所以 lambda 表达式可以像 m => m.StudentId
一样简单,我们都知道 m
的类型就是 TModel
的类型。在这种情况下,它是页面的视图模型。
我希望能够编写类似的代码,而不知道 属性 定义在什么类型上。我希望能够写...
@Html.EditorFor(M.StudentId) // here M is a type not a lambda parameter
@Html.EditorFor(X.Y) // here X is a type not a lambda parameter
我希望能够指定任意类型和任意参数,并使用可识别两者的内容调用该方法。例如,如果使用 PropertyInfo
调用该方法,那么我可以同时看到 属性 和定义它的类型。
换句话说...就像 nameof(X.Y)
为任意类型 X
给出字符串 "Y"
一样,我想要一个表达式,它给出类似PropertyInfo
也是。也许 property(X.Y)
并且您从类型 X
.
Y
的 PropertyInfo
您可以像 EditorFor
一样使用 属性 表达式。您可以在没有实例的情况下执行此操作。
一个区别是您必须指定表达式参数的类型来告诉编译器对象类型是什么。所以而不是
EditorFor( x => x.Name ); //Specifies a property but not a type
...你的表情应该是这样的:
EditorFor( (MyType x) => x.Name ); //Specifies property and the type it belongs to
您可以使用像这样的简短方法来完成此操作:
static PropertyInfo GetPropertyInfo<TIn, TOut>(Expression<Func<TIn, TOut>> expression)
{
var memberExp = expression.Body as MemberExpression;
return memberExp?.Member as PropertyInfo;
}
然后你可以这样做:
var p1 = GetPropertyInfo((string s) => s.Length);
Console.WriteLine("{0}.{1}", p1.DeclaringType.FullName, p1.Name);
var p2 = GetPropertyInfo((DateTime d) => d.Minute);
Console.WriteLine("{0}.{1}", p2.DeclaringType.FullName, p2.Name);
var p3 = GetPropertyInfo((Stream s) => s.CanSeek);
Console.WriteLine("{0}.{1}", p3.DeclaringType.FullName, p3.Name);
输出:
System.String.Length
System.DateTime.Minute
System.IO.Stream.CanSeek
请注意,我们从来不需要任何实例。