简体   繁体   中英

Can I write the method name without using a String to pass the name of the method? (c#)

I have got this class:

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

I need to pass the property name to a DataBinding:

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

I want to do something like this:

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

If you can use C#6, you have the nameof operator, which does just that.

string propertyName = nameof(foo.Val);

If you use C# 5, you can leverage expression trees:

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

Use this helper function like this (assuming it's in a ReflectionHelper class):

string propertyName = ReflectionHelper.GetPropertyName<foo>(x => x.Val);

This way, you can safely use refactorings in your IDE.

As of C# 6, you can use the nameof operator:

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

Before C# 6, there's no really simple way to do this at compile-time. One option, however, is to have unit tests which check that all your property names are actual properties (checking with reflection).

Also note that in C# 5 there's CallerMemberNameAttribute which is useful for implementing INotifyPropertyChanged - but isn't as useful for your case.

The approach of using expression trees works, but it feels somewhat clunky to me. Although far lower tech, simple string constants and a unit test feels a bit simpler.

If you are not using C# 6, you need to pass around an Expression<Func<T>> .

You can then do this with that object (if you are passing a property):

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

You would use this like:

var propName = GetPropertyName(() => this.Val);

I don't know if you're using INotifyPropertyChanged but there's some articles on how to avoid using "magic strings" here which may be of use:

Implementing NotifyPropertyChanged without magic strings

typesafe NotifyPropertyChanged using linq expressions

Check out statically typed reflection with LINQ: http://blogs.clariusconsulting.net/kzu/statically-typed-reflection-with-linq/

You can do:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM