我想知道以下代码是否“安全”。 “安全”是指我不依赖于某些特定的编译器版本或未记录的功能。 我想获取属性/字段名称的字符串,但我想使用强类型声明它(我希望编译器检查是否存在特定的字段/属性)。 我的方法如下:
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)
提前感谢您的帮助。
答案 0 :(得分: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
}
答案 1 :(得分:2)
我认为你的代码没问题。我没有看到任何问题。为了深入了解这一点,我建议您也阅读this article和this one。
答案 2 :(得分: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");
}