dlopezgonzalez
dlopezgonzalez

Reputation: 4297

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();

Upvotes: 1

Views: 156

Answers (5)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

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.

Upvotes: 5

Jon Skeet
Jon Skeet

Reputation: 1500535

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.

Upvotes: 1

Erti-Chris Eelmaa
Erti-Chris Eelmaa

Reputation: 26268

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;

Upvotes: 0

Tim Rutter
Tim Rutter

Reputation: 4679

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

Upvotes: 1

toadflakz
toadflakz

Reputation: 7944

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

Upvotes: 1

Related Questions