2010-11-24 61 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"); 
    }