2010-11-24 44 views
2

我想知道下面的代碼是否「安全」。通過「安全」我的意思是我不依賴於某些特定的編譯器版本或未記錄的功能。 我想獲得屬性/字段名稱的字符串,但我想用強類型聲明它(我希望編譯器檢查特定的字段/屬性是否存在)。 我的方法是這樣的:強類型屬性聲明 - 此代碼是否安全?

string GetPropertyName<T>(Expression<Func<T, object>> expression) 
{ 
    if (expression.Body is UnaryExpression) 
    { 
     var operand = ((UnaryExpression)expression.Body).Operand.ToString(); 
     return operand.Substring(operand.IndexOf(".") + 1); 
    } 
    else if (expression.Body is MemberExpression) 
    { 
     return ((MemberExpression)expression.Body).Member.Name; 
    } 
    else 
    { 
     throw new NotImplementedException(); 
    }    
} 

這裏是我要如何使用它:提前

class Foo 
{ 
    public string A { get; set; } 
    public Bar B { get; set; } 
} 

class Bar 
{ 
    public int C { get; set; } 
    public Baz D { get; set; } 
} 

class Baz 
{ 
    public int E { get; set; } 
} 


GetPropertyName<Foo>(x => x.A) 
GetPropertyName<Foo>(x => x.B) 
GetPropertyName<Foo>(x => x.B.C) 
GetPropertyName<Foo>(foo => foo.B.D.E) 

感謝您的幫助。

回答

3

我不確定以任何方式保證ToString方法的輸出。該文檔只是說它「返回Expression的文本表示。 (我懷疑輸出不太可能在不同的平臺/版本中改變,但當你的目標是使用強打字,編譯時檢查等等時,我會有點不情願)。

這裏是我的方法,做類似的事情,而無需使用ToString

public static string GetPropertyName<T>(Expression<Func<T, object>> e) 
{ 
    MemberExpression me; 
    switch (e.Body.NodeType) 
    { 
     case ExpressionType.Convert: 
     case ExpressionType.ConvertChecked: 
      var ue = e.Body as UnaryExpression; 
      me = ((ue != null) ? ue.Operand : null) as MemberExpression; 
      break; 
     default: 
      me = e.Body as MemberExpression; 
      break; 
    } 

    if (me == null) 
     throw new ArgumentException("Expression must represent field or property access.", "e"); 

    var stack = new Stack<string>(); 

    do 
    { 
     stack.Push(me.Member.Name); 
     me = me.Expression as MemberExpression; 
    } while (me != null); 

    return string.Join(".", stack); // use "stack.ToArray()" on .NET 3.5 
} 
2

我認爲你的代碼沒問題。我沒有看到任何問題。爲了深入瞭解這一點,我建議您閱讀this articlethis one

1
public static string GetPropertyName<T>(Expression<Func<T, object>> e) 
    { 
     if (e.Body is MemberExpression) 
      return ((MemberExpression)e.Body).Member.Name; 
     else if (e.Body is UnaryExpression) 
      return ((MemberExpression)((UnaryExpression)e.Body).Operand).Member.Name; 

     throw new ArgumentException("Expression must represent field or property access.", "e"); 
    }