【问题标题】:Getting sub property names strongly typed获取强类型的子属性名称
【发布时间】:2013-07-26 13:43:12
【问题描述】:

对于控件和网格的数据绑定对象,我讨厌属性名称是魔术字符串,所以我创建了一个非常简单的方法,如下所示:

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)

但是,这不是一个很好的解决方案。

【问题讨论】:

标签: c# .net linq


【解决方案1】:

这是我可能在 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;
    }
}

【讨论】:

  • 谢谢,我会在星期一试试这个。发布后几分钟,我发现了一种方法。等我回去工作,我会把它贴出来。
  • 好东西,只是我会将 TProperty 替换为 public static string GetPropertyName&lt;TProperty&gt;(this Expression&lt;Func&lt;TArg, object&gt;&gt; propertyExpression) 这样的对象,在这种情况下,您无需在使用扩展时指定属性类型,这不会影响其余代码.
  • @Giedrius,类型是自动推断的(假设您使用 MemberExpression)。因此,您不需要指定类型。编译:string propertyName = someMemberExpression.GetPropertyName();
  • 这取决于你如何使用它。我的变体允许这样写:criteria.Add(Restrictions.Eq(PropertyAccess.GetName&lt;Product&gt;(x =&gt; x.Category.Id), filter.CategoryId)),因为我还没有任何产品实例,只想创建选择标准。
【解决方案2】:

我想出了以下似乎可行的方法:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-04
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2020-02-28
    • 2012-01-08
    相关资源
    最近更新 更多