8

So I use the following utility to get the name of a field/property from an instance of a class...

public static string FieldName<T>(Expression<Func<T>> Source)
{
    return ((MemberExpression)Source.Body).Member.Name;
}

This allows me to do the following:

public class CoolCat
{
    public string KaratePower;
}

public class Program
{
    public static Main()
    {
        public CoolCat Jimmy = new CoolCat();

        string JimmysKaratePowerField = FieldName(() => Jimmy.KaratePower);
    }
}

This is great for serialization and other times when I need a string representation of the field name.

But now, I want to be able to get the field name WITHOUT having an instance of the class - for instance, if I am setting up a table and want to dynamically link the FieldNames of the columns to actual fields in a class (so refactorings, etc. will not break it).

Basically, I feel like I just don't quite get the syntax of how to accomplish this, but I imagine that it will look something like this:

public static string ClassFieldName<T>(Func<T> PropertyFunction)
{
     // Do something to get the field name?  I'm not sure whether 'Func' is the right thing here - but I would imagine that it is something where I could pass in a lambda type expression or something of the sort?
}

public class Program
{
    public static Main()
    {
        string CatsPowerFieldName = ClassFieldName<CoolCat>((x) => x.KaratePower);

        // This 'CatsPowerFieldName' would be set to "KaratePower".
    }
}

I hope that makes sense - I'm not very good with the vocab around this subject so I know that the question is a little vague.

Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
William
  • 3,335
  • 9
  • 42
  • 74

3 Answers3

4

What you're trying to do is one of the reasons Microsoft created System.Reflection Try this:

using System.Reflection;  // reflection namespace

public static List<Type> GetClassPropertyNames(Type myClass)
        {
            PropertyInfo[] propertyInfos;
            propertyInfos = myClass.GetProperties(BindingFlags.Public);

            List<Type> propertyTypeNames = new List<Type>();

            // write property names
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                propertyTypeNames .Add(propertyInfo.PropertyType);
            }

            return propertyNames;

        }
Jason Kulatunga
  • 5,814
  • 1
  • 26
  • 50
  • Note that this will return all public static properties. In the example a nonstatic field is used. – C.Evenhuis Jun 05 '12 at 14:37
  • I'm not sure that this helps me - I want to have a method that i can call that returns the string name of the field of a given class - how can I turn the above into something like that? – William Jun 05 '12 at 17:20
  • @William I've updated my example with your request, you can call it using: GetClassPropertyNames(typeof(CoolCat)); – Jason Kulatunga Jun 05 '12 at 17:31
  • But i don't want a list of string names - I want to be able to refer to the name of a SPECIFIC field when binding some UI component to a field - i.e. like when setting the field name property of a data column. – William Jun 05 '12 at 17:36
  • @William Well using reflection you can convert from a type name to a Type object, but thankfully the PropertyInfo object has a field PropertyType which returns the Type object. I've edited my answer again to return List – Jason Kulatunga Jun 05 '12 at 17:39
3

I have two methods I use to do this.

The first is an extension method that can be used on any object.

public static string GetPropertyName<TEntity, TProperty>(this TEntity entity, Expression<Func<TEntity, TProperty>> propertyExpression)
{
    return propertyExpression.PropertyName();
}

Which is used like

public CoolCat Jimmy = new CoolCat();
string JimmysKaratePowerField = Jimmy.GetPropertyName(j => j.KaratePower);

The second I use when I don't have an object.

public static string PropertyName<T>(this Expression<Func<T, object>> propertyExpression)
{
        MemberExpression mbody = propertyExpression.Body as MemberExpression;

        if (mbody == null)
        {
            //This will handle Nullable<T> properties.
            UnaryExpression ubody = propertyExpression.Body as UnaryExpression;

            if (ubody != null)
            {
                mbody = ubody.Operand as MemberExpression;
            }

            if (mbody == null)
            {
                throw new ArgumentException("Expression is not a MemberExpression", "propertyExpression");
            }
        }

        return mbody.Member.Name;
}

This can be used like so

string KaratePowerField = Extensions.PropertyName<CoolCat>(j => j.KaratePower);
cadrell0
  • 17,109
  • 5
  • 51
  • 69
  • I really like this solution - could you maybe elaborate about the section that you added handling Nullable properties? When would this section of code be used? – William Jun 07 '12 at 16:25
  • If KaratePower is a `Nullable` or `T?` such as `int?` or `DateTime?`, then the body will not be a MemberExpression, it will be a UnaryExpression. From there, you need to take the UnaryExpression's Operand to get the correct MemberExpression. – cadrell0 Jun 07 '12 at 16:43
2

I believe using Reflection will be useful here. I do not have VS with me right now, but I'm sure you can do something like typeof(class).GetMembers(). My reflection is a little rusty.

tylerjgarland
  • 643
  • 6
  • 19