Search code examples
c#reflectionfieldinfo

C#: is there a way to access the name of the current field?


In C#, I am defining a static field of a specific class. From within the class, I want to be able to display the name of the static field, pretty much like this:

public class Unit {
  public string NameOfField { get { return ...; } }
}

public static Unit Hectare = new Unit();

If I now access:

Hectare.NameOfField

I want it to return:

Hectare

I know there is a static function System.Reflection.MethodBase.GetCurrentMethod(), but as far as I can tell there is no way to get the name of the instance containing this current method?

There is also the System.RuntimeFieldHandle structure, but I have not been able to identify any GetCurrentFieldHandle() method.

I am not sure if I am missing something obvious?

Any help on this is very much appreciated.


Solution

  • Thanks everyone who has taken the time to answer and discuss my question.

    Just to let you know, I have implemented a solution that is sufficient for my needs. The solution is not general, and it has some pitfalls, but I'd thought I share it anyway in case it can be of help to someone else.

    This is in principle what the class that is used when defining fields looks like:

    public class Unit : IUnit {
      public NameOfField { get; set; }
      ...
    }
    

    As you can see, the class implements the IUnit interface, and I have provided a public setter in the NameOfField property.

    The static fields are typically defined like this within some containing class:

    public static Unit Hectare = new Unit();
    

    My solution is to set the NameOfField property through reflection before the field is used in the implementation. I do this through a static constructor (that of course needs to be invoked before the Unit fields are accessed. I use Linq to traverse the executing assembly for the relevant fields, and when I have detected these fields (fields which type implements the IUnit interface), I set the NameOfField property for each of them using the Any extension method:

    Assembly.GetExecutingAssembly().GetTypes().
      SelectMany(type => type.GetFields(BindingFlags.Public | BindingFlags.Static)).
      Where(fieldInfo => fieldInfo.FieldType.GetInterfaces().Contains(typeof(IUnit))).
      Any(fieldInfo =>
      {
        ((IUnit)fieldInfo.GetValue(null)).NameOfField= fieldInfo.Name;
        return false;
      });
    

    There are some shortcomings with this approach:

    • The static constructor has to be invoked through manual intervention before any Unit fields can be accessed
    • The NameOfField setter is public. In my case this is no problem, but it might be when applied in other scenarios. (I assume that the setter could be made private and invoked through further reflection, but I have not taken the time to explore that path further.)
    • ... ?

    Either way, maybe this solution can be of help to someone else than me.