我有这门课:
class foo
{
int val;
public int Val
{
set{ val = values; },
set{ val = values; }
}
}
我需要将属性名称传递给DataBinding:
String propertyName = "Val";
ctrl.DataBindings.Add(propertyName, object, dataMember, true, DataSourceUpdateMode.Never);
我想做这样的事情:
propertyName = typeof(foo).methods.Val.toString();
答案 0 :(得分:5)
如果您可以使用C#6,那么您就拥有了nameof
运算符。
string propertyName = nameof(foo.Val);
如果您使用C#5,则可以使用表达式树:
public static string GetPropertyName<TParent>(Expression<Func<TParent, object>> prop)
{
var expr = prop.Body;
if (expr.NodeType == ExpressionType.Convert)
expr = ((UnaryExpression)expr).Operand;
if (expr.NodeType == ExpressionType.MemberAccess)
return ((MemberExpression)expr).Member.Name;
throw new ArgumentException("Invalid lambda", "prop");
}
使用这样的辅助函数(假设它在ReflectionHelper
类中):
string propertyName = ReflectionHelper.GetPropertyName<foo>(x => x.Val);
这样,您可以安全地在IDE中使用重构。
答案 1 :(得分:1)
从C#6开始,您可以使用nameof
运算符:
ctrl.DataBindings.Add(nameof(foo.Val), /* other arguments as before */);
在C#6之前,在编译时没有非常简单的方法可以做到这一点。但是,一种选择是使用单元测试来检查所有属性名称是否为实际属性(使用反射进行检查)。
另请注意,在C#5中CallerMemberNameAttribute
对实施INotifyPropertyChanged
非常有用 - 但对您的案例并不有用。
使用表达式树的方法有效,但对我来说感觉有点笨拙。虽然技术要低得多,但简单的字符串常量和单元测试感觉更简单。
答案 2 :(得分:1)
如果您不使用C#6,则需要传递Expression<Func<T>>
。
然后,您可以使用该对象执行此操作(如果要传递属性):
private string GetPropertyName(Expression<Func<T>> propertyExpession)
{
//the cast will always succeed if properly used
MemberExpression memberExpression = (MemberExpression)propertyExpression.Body;
string propertyName = memberExpression.Member.Name;
return propertyName;
}
您可以使用它:
var propName = GetPropertyName(() => this.Val);
答案 3 :(得分:1)
我不知道您是否正在使用INotifyPropertyChanged,但有一些关于如何避免在这里使用“魔术字符串”的文章可能有用:
答案 4 :(得分:0)
使用LINQ检查静态类型反射:http://blogs.clariusconsulting.net/kzu/statically-typed-reflection-with-linq/
你可以这样做:
string propertyName = Reflect<foo>.GetProperty(x => x.Val).Name;