Home > database >  Generically get the name of the current class?
Generically get the name of the current class?

Time:08-25

When logging data, I want a generic reference to the containing class. That way, if the code is moved elsewhere, the class name will change accordingly. (Otherwise, if the code moves to nameof(Class2), it will still be logged incorrectly as nameof(Class1)). For example:

class Class_Name {
   ICommand Command_Name =>
        new RelayCommand(() =>
        {
           // An loggable event occurs

           // Is there a smart and uncomplicated way of doing this generically?
           var provenance = $"{nameof(Class_Name)}.{nameof(Command_Name)}";

           // The event of whatever kind gets logged
      });
   }

   // OR
   void Method_Name() {
      var provenance = $"{nameof(Class_Name)}.{nameof(Method_Name)}";
   }
}

Using a generic nameof(this), where this should refer to the class itself, causes a compilation error: CS8081: Expression does not have a name. Using this.GetType() causes the same problem.

Not really understanding why the this keyword does not refer to the containing class in this context. Is there a way to refer to the current class generically?

CodePudding user response:

If you combine the suggestion in the comments (this.GetType().Name) with a [CallerMemberName] attribute via a helper method, you can accomplish what you're looking for in a reusable fashion.

public class Class_Name
{
    public void Method_Name()
    {
        var provenance = CreateProvenance();
        Console.WriteLine(provenance);
    }

    private string CreateProvenance([CallerMemberName] string methodName = "")
    {
        return $"{this.GetType().Name}.{methodName}";
    }
}

This outputs "Class_Name.Method_Name".

You can even turn this into a handy extension method that allows you to call it from any method.

public class Class_Name
{
    public void Method_Name()
    {
        var provenance = this.CreateProvenance();
        Console.WriteLine(provenance);
    }
}

public static class ProvenanceExtensions
{
    public static string CreateProvenance(this object context, 
        [CallerMemberName] string methodName = "")
    {
        return $"{context.GetType().Name}.{methodName}";
    }
}

CodePudding user response:

By design:

A nameof expression is evaluated at compile time and has no effect at run time.

To access the type dynamically, in the runtime, you may use the GetType method. Just rememeber not to combine it with the nameof.

class Class_Name {
   void Method_Name() {
      // An event occurs

      // Is there a smart and uncomplicated way of doing this generically?
      var provenance = $"{this.GetType().Name}.{MethodBase.GetCurrentMethod().Name}";

      // The event of whatever kind gets logged
   }
}
  • Related