Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting property names of a class using expressions, static methods, and a base object

Tags:

c#

.net

linq

c#-4.0

I have a common problem, that I am trying to get round in a specific way.

Basically with Winforms, I am trying to set the "DisplayMember" and "ValueMember" of controls in a form. You would normally set it like so:

this.testCombobox.DisplayMember = "PropertyOne";
this.testCombobox.ValueMember = "PropertyTwo";

I want to rewrite this as follows:

this.testCombobox.DisplayMember = ClassOne.GetPropertyName(c => c.PropertyOne);
this.testCombobox.ValueMember = ClassOne.GetPropertyName(c => c.PropertyTwo);

(NOTE: the 2 method calls need to be static, to save creating objects here)

All of my classes that I am trying to do this, inherit from a base class "BaseObject", so I have added a method to it as follows:

public static string GetPropertyName<T, P>(Expression<Func<T, P>> action) where T : class
{
    MemberExpression expression = action.Body as MemberExpression;
    return expression.Member.Name;
}

However, in order to use this, I need to write the following code instead:

this.testCombobox.DisplayMember = BaseObject.GetPropertyName((ClassOne c) => c.PropertyOne);

My question is, how would I rewrite the method BaseObject.GetPropertyName to achieve what I want? I feel I am very close but cannot think how to change it.

like image 820
eyeballpaul Avatar asked Feb 15 '23 21:02

eyeballpaul


2 Answers

Your current GetPropertyName method leaves open the generic T. Hence, the compiler cannot resolve it compile-time since you do not specify it when you use the method.

However, if you make your base class generic, AND specify the T in the derived class, AND specify to use the method of the derived class (and not the base class), then it works.

Like this:

public class BaseClass<T> {
    public static string GetPropertyName<P>(Expression<Func<T, P>> action) {
        MemberExpression expression = action.Body as MemberExpression;
        return expression.Member.Name;
    }
}

public class ClassOne : BaseClass<ClassOne> {
    public string PropertyOne { get; set; }
}
public static class Test {
    public static void test() {
        var displayMember = ClassOne.GetPropertyName(x => x.PropertyOne);
    }
}
like image 72
Maarten Avatar answered Feb 18 '23 14:02

Maarten


I created a Helper class to extract Proprty Name

  public static class PropertySupport
  {       
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
      if (propertyExpression == null)
      {
        throw new ArgumentNullException("propertyExpression");
      }

      var memberExpression = propertyExpression.Body as MemberExpression;
      if (memberExpression == null)
      {
        throw new ArgumentException("Invalide Expression", "propertyExpression");
      }             
      return memberExpression.Member.Name;
    }
  }

And you can use it as Follows :

PropertySupport.ExtractPropertyName(() => DateTime.Now)

it will return "Now"

EDIT

Here is a test console app:

  public static class PropertySupport
  {       
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
      if (propertyExpression == null)
      {
        throw new ArgumentNullException("propertyExpression");
      }

      var memberExpression = propertyExpression.Body as MemberExpression;
      if (memberExpression == null)
      {
        throw new ArgumentException("", "propertyExpression");
      }      
      return memberExpression.Member.Name;
    }
  }
  public class MyClass
  {
    public MyClass PropertyOne { get; set; }
  }
  class Program
  {    
    static void Main(string[] args)
    {      
      Console.WriteLine(PropertySupport.ExtractPropertyName(() => new MyClass().PropertyOne));
      Console.ReadKey();
    }   
  }
like image 41
Swift Avatar answered Feb 18 '23 14:02

Swift