是否可以在不使用字符串传递方法名称的情况下编写方法名称?(C#)

本文关键字:方法 情况下 字符串 是否 | 更新日期: 2023-09-27 18:34:05

我有这个类:

class foo
{
   int val;
   public int Val
   {
      set{ val = values; },
      set{ val = values; }
   }
}

我需要将属性名称传递给数据绑定:

String propertyName = "Val";
ctrl.DataBindings.Add(propertyName, object, dataMember, true, DataSourceUpdateMode.Never);

我想做这样的事情:

propertyName = typeof(foo).methods.Val.toString();

是否可以在不使用字符串传递方法名称的情况下编写方法名称?(C#)

如果可以使用 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 中安全地使用重构。

如果不使用 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);
我不知道

你是否正在使用INotifyPropertyChanged,但这里有一些关于如何避免使用"魔术字符串"的文章,这些文章可能会有用:

实现 NotifyPropertyChanged 没有魔术字符串

类型安全 通知属性已使用 linq 表达式更改

从 C# 6 开始,可以使用 nameof 运算符:

ctrl.DataBindings.Add(nameof(foo.Val), /* other arguments as before */);

在 C# 6 之前,没有真正简单的方法可以在编译时执行此操作。但是,一种选择是进行单元测试,以检查所有属性名称是否都是实际属性(使用反射进行检查)。

另请注意,在 C# 5 中,有CallerMemberNameAttribute它对实现INotifyPropertyChanged很有用 - 但对你的情况没有那么有用。

使用表达式树的方法有效,但对我来说感觉有些笨拙。虽然技术要低得多,但简单的字符串常量和单元测试感觉要简单一些。

使用 LINQ 签出静态类型反射:http://blogs.clariusconsulting.net/kzu/statically-typed-reflection-with-linq/

你可以做:

string propertyName = Reflect<foo>.GetProperty(x => x.Val).Name;