Home > Back-end >  Getting property name from within property type
Getting property name from within property type

Time:10-17

I couldn't figure out how to formulate the title any better. I see quite a few posts with similar titles but which discuss entirely different stuff.

So here we go. The actual on-ground situation is complex, but I'll try to post an absolute minimalistic example to describe it.

Let's say we have a class named Animal:

class Animal
{
  public void Run()
  {
    try
    {
      //try running
    }
    catch(Exception e)
    {
      MessageBox.Show(this.SomeCleverWayOfGettingPropertyName()   " failed to run");
    }
  }
}

Now I define several properties of Animal type in another class:

class Zoo
{
  public Animal Zebra {get; set;}
  public Animal Lion {get; set;}
  public Animal Rhino {get; set;}

  public void RunAll()
  {
    Zebra.Run();
    Lion.Run();
    Rhino.Run();
  }
}

What do I write in place of SomeCleverWayOfGettingPropertyName() to let it show name of the animal (that is name of the declared property), like "Zebra failed to run".

As I said, the actual situation is more complex, so kindly avoid answers like, "why don't you redesign your entire code base and instead try X". My hope is to find something in System.Reflection to find out the calling member's name, but I haven't found anything like that yet.

CodePudding user response:

Ideally you would rethink your problem, and possibly catch outside of the run

Depending on your exact needs, an expression might work.. However it really is a terrible solution, if you went to all the effort you might as well catch outside, or just pass the member name in.

Given

public class Animal
{
   public void Run()
   {
      Console.WriteLine("Running");
   }
}

public static class MemberInfoGetting
{
   public static void Run<T>(this Expression<Func<T>> memberExpression) where T : Animal
   {
      var expressionBody = (MemberExpression)memberExpression.Body;
      try
      {

         var animal = Expression.Lambda<Func<Animal>>(expressionBody).Compile()();
         animal.Run();
         throw new Exception("bob");
      }
      catch
      {
         Console.WriteLine($"{expressionBody.Member.Name} : failed to run");
      }
   }
}

Usage

public static Animal Rhino { get; set; } = new Animal();

public static void Main()
{
   MemberInfoGetting.Run(() => Rhino);
}

Output

Running
Rhino : failed to run

CodePudding user response:

you can try this:

class Animal
{
  public void Run([CallerMemberName] string caller = null)
  {
    try
    {
      //try running
    }
    catch(Exception e)
    {
      MessageBox.Show(caller   " failed to run");
    }
  }
}

CodePudding user response:

This is basically not possible with this approach. What happens when you call Zebra.Run():

  • Runtime calls the auto-generated get_Zebra() method, putting the Zebra's Animal instance pointer on the stack.
  • Runtime calls the Animal.Run() instance method.

All variable/property info about where that instance came from is pretty much gone at that point.

Now Animal.Run() doesn't know it's being called on an instance that came from a property, and there's no guarantee it will be. It could as well be a local, a method parameter or a new()ed instance, one from a factory or a collection element. You'll have to pass this info yourself.

Alternatively, if it's for error handling, it may be easier than you think without having to resolve to compiler magic or expensive expression refactoring:

In your exception handler, log the relevant properties that identify the Animal instance. Combined with the stack trace, this should give you enough information.

  • Related