Получение имен вложенных свойств строго типизированных

1

С привязкой объектов привязки к элементам управления и сеткам я ненавидел, как имена свойств будут магическими строками, поэтому я создал очень простой метод следующим образом:

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)

Однако это не простое решение.

Теги:
linq

2 ответа

0
Лучший ответ

Я придумал следующее, которое, похоже, работает:

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;
}
3

Это модифицированная версия того, что я мог бы найти здесь, в 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;
    }
}
  • 0
    Спасибо, я попробую это в понедельник. Через несколько минут после публикации я наткнулся на способ сделать это. Я опубликую это, как только вернусь к работе.
  • 0
    Отличный материал, просто я бы заменил TProperty на объект, подобный этой public static string GetPropertyName<TProperty>(this Expression<Func<TArg, object>> propertyExpression) , в таком случае вам не нужно указывать тип свойства при использовании расширения и это не влияет на остальную часть кода.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню