2013-07-26 202 views
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) 

然而,這不是一個巧妙的解決辦法。

+0

的[獲取財產可能重複,作爲一個字符串,從一個表達式>](http://stackoverflow.com/questions/2789504/get-the-property-as-a-string-from-an-expressionfunctmodel-tproperty) – nawfal

回答

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

這東西修改後的版本,我可能已經在這裏找到了計算器:

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

謝謝我會在星期一嘗試。發佈後幾分鐘,我遇到了一個辦法。一旦我重新開始工作,我會把它貼出來。 – eyeballpaul

+0

偉大的東西,只是我會用像這樣的公共靜態字符串GetPropertyName (此表達式> propertyExpression)替換TProperty,在這種情況下,您不需要指定使用擴展時的屬性類型這並不影響其他代碼。 – Giedrius

+0

@Giedrius,類型是自動推斷的(假設你使用MemberExpression)。因此你不需要指定類型。這編譯:'string propertyName = someMemberExpression.GetPropertyName();' – lightbricko