С привязкой объектов привязки к элементам управления и сеткам я ненавидел, как имена свойств будут магическими строками, поэтому я создал очень простой метод следующим образом:
public static string GetPropertyName<PropertyType>(Expression<Func<T, PropertyType>> expressionForProperty)
{
MemberExpression expression = expressionForProperty.Body as MemberExpression;
return expression.Member.Name;
}
Это позволяет мне использовать код, например:
Product.GetPropertyName(m => m.Name)
чтобы вернуть "Имя".
Это отлично работает для базовых объектов. Однако, если я изменяю вызов метода:
Product.GetPropertyName(m => m.ProductCategory.Name)
Это также возвращает "Имя". Но для того, чтобы привязка данных работала, мне понадобится вернуть "ProductCategory.Name". Есть ли способ, которым я могу это сделать, изменив метод "GetPropertyName"?
Возможным обходным путем было бы сделать это:
string test = Product.GetPropertyName(p => p.ProductCategory) + "." + ProductCategory.GetPropertyName(pc => pc.Name)
Однако это не простое решение.
Я придумал следующее, которое, похоже, работает:
public static string GetComplexPropertyName<PropertyType>(Expression<Func<T, PropertyType>> expressionForProperty)
{
// get the expression body
Expression expressionBody = expressionForProperty.Body as MemberExpression;
string expressionAsString = null;
// all properties bar the root property will be "convert"
switch (expressionBody.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
UnaryExpression unaryExpression = expressionBody as UnaryExpression;
if (unaryExpression != null)
{
expressionAsString = unaryExpression.Operand.ToString();
}
break;
default:
expressionAsString = expressionBody.ToString();
break;
}
// makes ure we have got an expression
if (!String.IsNullOrWhiteSpace(expressionAsString))
{
// we want to get rid of the first operand as it will be the root type, so get the first occurence of "."
int positionOfFirstDot = expressionAsString.IndexOf('.');
if (positionOfFirstDot != -1)
{
return expressionAsString.Substring(positionOfFirstDot + 1, expressionAsString.Length - 1 - positionOfFirstDot);
}
}
return string.Empty;
}
Это модифицированная версия того, что я мог бы найти здесь, в StackOVerflow:
public static class GetPropertyNameExtension
{
public static string GetPropertyName<TArg, TProperty>(this Expression<Func<TArg, TProperty>> propertyExpression)
{
return propertyExpression.Body.GetMemberExpression().GetPropertyName();
}
public static string GetPropertyName<TProperty>(this Expression<Func<TProperty>> propertyExpression)
{
return propertyExpression.Body.GetMemberExpression().GetPropertyName();
}
public static string GetPropertyName(this MemberExpression memberExpression)
{
if (memberExpression == null)
{
return null;
}
if (memberExpression.Member.MemberType != MemberTypes.Property)
{
return null;
}
var child = memberExpression.Member.Name;
var parent = GetPropertyName(memberExpression.Expression.GetMemberExpression());
return parent == null ?
child
: parent + "." + child;
}
public static MemberExpression GetMemberExpression(this Expression expression)
{
if (expression is MemberExpression)
return (MemberExpression)expression;
if (expression is UnaryExpression)
return (MemberExpression)((UnaryExpression)expression).Operand;
return null;
}
}
public static string GetPropertyName<TProperty>(this Expression<Func<TArg, object>> propertyExpression)
, в таком случае вам не нужно указывать тип свойства при использовании расширения и это не влияет на остальную часть кода.