2010-11-24 4 views
2

Ich frage mich, ob der folgende Code "sicher" ist. Mit "sicher" meine ich, dass ich nicht auf eine bestimmte Compiler-Version oder undokumentierte Funktion angewiesen bin. Ich möchte Zeichenfolge mit Eigenschaft/Feldname erhalten, aber ich möchte es mit starker Typisierung deklarieren (Ich möchte der Compiler überprüfen, ob ein bestimmtes Feld/Eigenschaft existiert). Meine Methode sieht wie folgt aus:Stark typisierte Eigenschaftsdeklarationen - ist dieser Code sicher?

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

Und hier ist, wie ich will, es benutzen:

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) 

Vielen Dank im Voraus für die Hilfe.

Antwort

3

Ich bin mir nicht sicher, ob die Ausgabe der ToString Methode in irgendeiner Weise garantiert ist. Die Dokumentation sagt nur, dass es "eine Textdarstellung der Expression" zurückgibt.

(Ich vermute, dass der Ausgang unwahrscheinlich ist, über verschiedene Plattformen/Versionen zu ändern, aber ich würde ein bisschen zögern, darauf zu verlassen, wenn Sie Ihr Ziel starke Typisierung zu verwenden ist, Compiler-Kontrollen etc.)

Hier ist meine Methode, die ohne ToString mit etwas ähnliches tut:

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

Ich denke, Sie Code ist in Ordnung. Ich sehe keine Probleme. Um ein wenig tiefer in dieses Thema zu kommen, empfehle ich Ihnen, auch this article und this one zu lesen.

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