Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# How to get the name of the property being set

I have a database object class that does a bunch of heavy lifting. I then extend that object and build out the classes that represent the actual objects and fields being modified. It basically looks like this:

public class MyObject : DatabaseObject
{
    public string FieldX
    {
        get { return GetValue<string>("FieldX"); }
        set { SetValue<string>("FieldX", value); }
    }

    public int FieldY
    {
        get { return GetValue<int>("FieldY"); }
        set { SetValue<int>("FieldY", value); }
    }
}

public class DatabaseObject
{
    public T GetValue<T>(string FieldName)
    {
         // Code that actually gets the right value
    }

    public void SetValue<T>(string FieldName, T value)
    {
         // Code that actually sets the value in the right place
    }
}

This way, I can later just instantiate MyObject and start setting the properties via code. The idea is to produce easier, more maintainable code.

It works great in practice. However, I'm noticing that the code for MyObject is pretty repetitive. For example, with FieldX, I end up specifying the "string" type inside the get/set, and also having to specify the property name "FieldX" in get/set, as well.

I'm wondering if there's a way to simplify the code further to reduce repetition.

I know I can use Reflection:

MethodBase.GetCurrentMethod().Name.Substring(4)

...inside the get/set calls to get the property name, and I can use GetType() to get the type of value when doing set, but ideally I'd like to get the original property name from within the base GetValue/SetValue methods (ideally without parsing the stack trace).

Ideally, I'm looking for something like this:

    public string FieldX
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }

    public int FieldY
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }

Any thoughts?

like image 484
jhilgeman Avatar asked Dec 10 '13 23:12

jhilgeman


2 Answers

This is a bit longer, than you looking for, but also can be used (using strongly-typed lambda expressions).

public class MyObject : DatabaseObject
{
    public string FieldX
    {
        get { return GetValue(() => FieldX); }
        set { SetValue(() => FieldX, value); }
    }

    public int FieldY
    {
        get { return GetValue(() => FieldY); }
        set { SetValue(() => FieldY, value); }
    }
}

public class DatabaseObject
{
    public T GetValue<T>(Expression<Func<T>> field)
    {
         string fieldName = GetFieldName(field);
         // Code that actually gets the right value
    }

    public void SetValue<T>(Expression<Func<T>> field, T value)
    {
         string fieldName = GetFieldName(field);
         // Code that actually sets the value in the right place
    }

    private static string GetFieldName<T>(Expression<Func<T>> field)
    {
        return ((MemberExpression)field.Body).Member.Name;
    }
}
like image 41
Shad Avatar answered Nov 01 '22 12:11

Shad


C# 5.0 supports this by using the [CallerMemberName] attribute on a default parameter. Something like this:

public static object GetValue([CallerMemberName] string caller = "")
{
    Trace.WriteLine("Called by: " + caller);
    return null;
}

And would be used like:

public string FieldX
{
    get { return (string)GetValue(); }
}

This works by the compiler automatically supplying the parameter of GetValue based on the caller's name.

You can learn more about this feature in MSDN.

You can probably make GetValue generic so it can be used like GetValue<string>() in your properties.

like image 75
vcsjones Avatar answered Nov 01 '22 13:11

vcsjones