Building a method using lambda expressions call
I'm building a method to get the DisplayAttribute 开发者_JS百科from System.ComponentModel.DataAnnotations to show on a label for the property.
[Display(Name="First Name")]
public string FirstName { get; set; }
The method is working well:
string GetDisplay(Type dataType, string property)
{
PropertyInfo propInfo = dataType.GetProperty(property);
DisplayAttribute attr = propInfo.GetCustomAttributes(false).OfType<DisplayAttribute>().FirstOrDefault();
return (attr == null) ? propInfo.Name : attr.Name;
}
The call of method can be:
lblNome.Text = GetDisplay(typeof(Person), "FirstName") + ":";
I can use a more elegant sintax using Generics, like:
string GetDisplay<T>(string property)
{
PropertyInfo propInfo = typeof(T).GetProperty(property);
DisplayAttribute attr = propInfo.GetCustomAttributes(false).OfType<DisplayAttribute>().FirstOrDefault();
return (attr == null) ? propInfo.Name : attr.Name;
}
And the call:
GetDisplay<Person>("FirstName");
So, I would like to make it more more elegant using lambda expressions turning the call like this:
GetDisplay<Person>(p => p.FirstName);
The question is how can I achieve this?
Here is the method I use to fetch property name given by lambda expression:
public static string PropertyName<T1, T2>(this Expression<Func<T1, T2>> expression)
{
MemberExpression member = null;
if (expression.Body is MemberExpression)
member = expression.Body as MemberExpression;
if (expression.Body is UnaryExpression && expression.Body.NodeType == ExpressionType.Convert)
member = ((UnaryExpression)expression.Body).Operand as MemberExpression;
if (member == null)
throw new ArgumentException("Selector must point to a property or field.", "expression");
return member.Member.Name;
}
Using this method you can just call the previous method:
string GetDisplay<T>(Expression<Func<T, object>> expression)
{
return GetDisplay<T>(expression.PropertyName());
}
精彩评论