CallerMemberName funktioniert nicht

  • C#
  • .NET 5–6

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von MasterQ.

    CallerMemberName funktioniert nicht

    Hallo,

    ich habe zwei sehr ähnliche Konstrukte mit dem Attribut CallerMemberName

    Logger:

    C#-Quellcode

    1. public interface ILoggerService
    2. {
    3. void Information(object? sender, string message, string methode = "");
    4. void Information(string message);


    C#-Quellcode

    1. public void Information(object? sender, string message, [CallerMemberName] string methode = "")
    2. {
    3. Logger?.LogInformation($"{Classname(sender)}.{methode}: {message}");
    4. }
    5. public void Information(string message)
    6. {
    7. Logger?.LogInformation(message);
    8. }
    9. private string Classname(object? obj)
    10. {
    11. return obj?.GetType().FullName ?? "N/A";
    12. }



    Und in der Fehlerbehandlung:

    C#-Quellcode

    1. public interface IErrorHandler
    2. {
    3. void Set(object? sender, string message, ErrorHandler.ErrorLevels level, string methode = "");


    C#-Quellcode

    1. public void Set(object? sender, string message, ErrorLevels level, [CallerMemberName] string methode = "")
    2. {
    3. ClassName = sender?.GetType().FullName ?? "N/A";
    4. Message = message;
    5. ErrorLevel = level;
    6. MethodeName = methode;
    7. //Show();
    8. }



    Im ersten Fall, dem Logger wird der letzte Parameter methode korrekt gefüllt. Im zweiten Fall bleibt methode leer. Ich versteh nicht warum.


    Testfunktion:

    C#-Quellcode

    1. private void Fehler()
    2. {
    3. Logger?.Information(this, "Meldung");
    4. Err?.Set(this, "Meldung", ErrorHandler.ErrorLevels.Informal);
    5. Err?.Show();
    6. }


    C#-Quellcode

    1. public bool Show()
    2. {
    3. Logging();



    C#-Quellcode

    1. private void Logging()
    2. {
    3. if (_logger != null)
    4. switch (ErrorLevel)
    5. {
    6. case ErrorLevels.None:
    7. case ErrorLevels.Informal:
    8. _logger.Information(Ask());
    9. break;



    C#-Quellcode

    1. public string Ask()
    2. {
    3. return $"{Source()}: {Message}";
    4. }
    5. public string Source()
    6. {
    7. string classname;
    8. string methodname;
    9. if (string.IsNullOrEmpty(ClassName))
    10. classname = "N/A";
    11. else classname = ClassName;
    12. if (string.IsNullOrEmpty(MethodeName))
    13. methodname = "N/A";
    14. else
    15. methodname = MethodeName;
    16. return $"{classname}.{methodname}";
    17. }


    Ausgabe:

    Logger: [2023-09-09T13:58.13.375] [Information] JHXManager.ViewModels.MainWindowViewModel.Fehler: Meldung

    Logger in Fehlerbehandlung: [2023-09-09T13:58.13.380] [Information] JHXManager.ViewModels.MainWindowViewModel.N/A: Meldung


    Aber was soll da zwischen den beiden Fällen anders sein. Ich blick es nicht.

    Gruß

    Joachim

    PS.: fehlende Klammern "}" deuten darauf hin, dass es in dieser KLasse bzw. Methode noch weiter geht.
    Sorry, beim Formulieren war ich noch tief in der Problematik. Ich versuche es noch einmal und kürze den Text bzw. vereinfache

    Zwei Fälle:
    1) LoggerService, Instanz Logger, Methode Information
    2) ErrorHandler, Instanz Err, Methode Set

    beide werden zu Testzwecken in einer Methode Fehler des Hauptfensters aufgerufen.

    Dem Logger.Information wird der Name der aufrufenden Methode automatisch wegen des Attributs CallaMemberName übergeben. Die Methode Set ist genauso gestrickt wie Information. In Set funktioniert das mit dem CallerMemberName irgendwie nicht.


    Nochmal anders.

    Methode Logger.Information:
    Aufruf: Logger?.Information(this, "Meldung");
    Diese bastelt sich aus this, "Meldung" und dem wegen CallerMemberName automatisch übergebenen Methodennamen ein Eintrag für das Logfile.

    Ein Teil Ausgabe lautet: JHXManager.ViewModels.MainWindowViewModel.Fehler
    JHXManager.ViewModels.MainWindowViewModel ist der Name der Klasse in der die aufrufende Methode steckt und Fehler der der aufrufenden Methode.


    Methode Err.Set:
    Aufruf: Err?.Set(this, "Meldung", ErrorHandler.ErrorLevels.Informal);
    Die ist praktisch genauso aufgebaut und erwartet ebenfalls den Methodennamen über CallerMemberName. Das funktioniert nicht. Der Methodenname Fehler wird offensichtlich nicht übergeben, sondern nur ein Leerstring. Die in der Fehlerbehandlung gebastelte Meldung wird genauso wie im Logger zusammengesetzt und ergibt aber ein

    JHXManager.ViewModels.MainWindowViewModel

    Der Methodenname fehlt weil leer.

    Ich hoffe, ich konnte es jetzt etwas klarer formulieren.
    Die LogInformation-Methode des Loggers (oder für den Logger?) aus Post#1 wird erwähnt, aber nicht definiert. Fischen im Trüben :/
    Wird bei der Error-Klasse vielleicht nochmal eine andere Methode aufgerufen und dann vergessen, den automatisch befüllten Parameter weiterzugeben?
    Mit dem hier klappt es, wie gewünscht. Finde den Unterschied und berichte:
    Spoiler anzeigen

    C#-Quellcode

    1. namespace ConsoleCS {
    2. class Program {
    3. private static Logger Logger = new Logger();
    4. private static Error Error = new Error();
    5. static void Main(string[] args) {
    6. Information(Logger, "Foo");
    7. Error.Set(Logger, "Bar");
    8. }
    9. static public void Information(object sender, string message, [CallerMemberName] string method = "")
    10. {
    11. Logger.Information($"{Classname(sender)}.{methode}: {message}", message, method);
    12. }
    13. static private string Classname(object obj)
    14. {
    15. return obj?.GetType().FullName ?? "N/A";
    16. }
    17. }
    18. public class Logger
    19. {
    20. public void Information(object sender, string message, string method = "")
    21. {
    22. //method enthält "Main"
    23. }
    24. }
    25. public class Error {
    26. private string ClassName;
    27. private string Message;
    28. private string MethodName;
    29. public void Set(object sender, string message, [CallerMemberName] string method = "")
    30. {
    31. ClassName = sender?.GetType().FullName ?? "N/A";
    32. Message = message;
    33. MethodName = method;
    34. //method enthält "Main"
    35. }
    36. }
    37. }


    Notfalls lad ein funktionierendes Testprojekt hoch, vielleicht kommen wir dann damit weiter.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    1) Ich nutze die Standardroutinen aus Microsoft.Extensions.Logging;

    2) den einzigen Unterschied den ich finden kann, ist, dass beide in unterschiedlichen DLL zu finden sind.

    Ich habe jetzt mal beide DLL-Quelltexte in ein Consoleprojekt kopiert und da funktioniert es. Also was ist an den DLL anders?

    Beide DLL in mein Testprojekt eingebunden und es funktioniert ebenso!


    :evil: hmm, Bin jetzt mal ratlos!