C # How to get the name of a set property

I have a database object class that does a ton of hard work. Then I extend this object and build classes that represent real objects and mutable fields. 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 } } 

That way, I can later simply create an instance of MyObject and start setting properties using code. The idea is to create simpler and more convenient code.

It works great in practice. However, I notice that the code for MyObject is pretty repetitive. For example, with FieldX, I finish specifying the type “string” inside get / set, and also specify the name of the property “FieldX” in get / set, as well.

I am wondering if there is a way to simplify the code in order 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 the value when the set is executed, but ideally I would like to get the original property name from the inside of the GetValue / SetValue base 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?

+6
source share
2 answers

This is slightly longer than what you are looking for, but can also 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; } } 
+3
source

C # 5.0 supports this with the default [CallerMemberName] attribute. Something like that:

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

And will be used as:

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

This works as a compiler that automatically passes the GetValue parameter based on the caller’s name.

You can learn more about this feature on MSDN .

Perhaps you can make GetValue generic so that it can be used as GetValue<string>() in your properties.

+7
source

All Articles