当通过lambda表达式传入时,是否有更好的方法来获得属性名?
这是我目前拥有的。
eg.
GetSortingInfo<User>(u => u.UserId);
它只在属性为字符串时才将其转换为成员表达式。因为不是所有的属性都是字符串,我必须使用object,但它会为那些返回一个unaryexpression。
public static RouteValueDictionary GetInfo<T>(this HtmlHelper html,
Expression<Func<T, object>> action) where T : class
{
var expression = GetMemberInfo(action);
string name = expression.Member.Name;
return GetInfo(html, name);
}
private static MemberExpression GetMemberInfo(Expression method)
{
LambdaExpression lambda = method as LambdaExpression;
if (lambda == null)
throw new ArgumentNullException("method");
MemberExpression memberExpr = null;
if (lambda.Body.NodeType == ExpressionType.Convert)
{
memberExpr =
((UnaryExpression)lambda.Body).Operand as MemberExpression;
}
else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpr = lambda.Body as MemberExpression;
}
if (memberExpr == null)
throw new ArgumentException("method");
return memberExpr;
}
我发现了另一种方法,就是让源和属性具有强类型,并显式地推断lambda的输入。不确定这是否是正确的术语,但这是结果。
public static RouteValueDictionary GetInfo<T,P>(this HtmlHelper html, Expression<Func<T, P>> action) where T : class
{
var expression = (MemberExpression)action.Body;
string name = expression.Member.Name;
return GetInfo(html, name);
}
然后像这样叫它。
GetInfo((User u) => u.UserId);
瞧,它起作用了。
我最近做了一件非常类似的事情来创建一个类型安全的OnPropertyChanged方法。
下面是一个方法,它将返回表达式的PropertyInfo对象。如果表达式不是属性,则抛出异常。
public PropertyInfo GetPropertyInfo<TSource, TProperty>(
TSource source,
Expression<Func<TSource, TProperty>> propertyLambda)
{
Type type = typeof(TSource);
MemberExpression member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
propertyLambda.ToString()));
PropertyInfo propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
propertyLambda.ToString()));
if (type != propInfo.ReflectedType &&
!type.IsSubclassOf(propInfo.ReflectedType))
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a property that is not from type {1}.",
propertyLambda.ToString(),
type));
return propInfo;
}
使用源参数,编译器可以对方法调用进行类型推断。您可以执行以下操作
var propertyInfo = GetPropertyInfo(someUserObject, u => u.UserID);
从。net 4.0开始,你可以使用ExpressionVisitor来查找属性:
class ExprVisitor : ExpressionVisitor {
public bool IsFound { get; private set; }
public string MemberName { get; private set; }
public Type MemberType { get; private set; }
protected override Expression VisitMember(MemberExpression node) {
if (!IsFound && node.Member.MemberType == MemberTypes.Property) {
IsFound = true;
MemberName = node.Member.Name;
MemberType = node.Type;
}
return base.VisitMember(node);
}
}
下面是如何使用这个访问者:
var visitor = new ExprVisitor();
visitor.Visit(expr);
if (visitor.IsFound) {
Console.WriteLine("First property in the expression tree: Name={0}, Type={1}", visitor.MemberName, visitor.MemberType.FullName);
} else {
Console.WriteLine("No properties found.");
}