Laden...

Aktuellen Namespace-, Class- und Methode-Namen ermitteln

Erstellt von Quaneu vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.886 Views
Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 13 Jahren
Aktuellen Namespace-, Class- und Methode-Namen ermitteln

Hallo,

ich stehe gerade vor folgendem Problem:

Ich habe eine statische Klasse Logger, mit deren Hilfe ich mein LogFile erzeugen will.
Dazu biete ich drei Methoden an, für Warnings, Errors und Messages.

Beispiel:


public static void WriteMessage(object sender, message)
{
...
}

Mein Wunsch wäre es jetzt über den sender mitzuteilen, in welcher Methode (Namespace und Class) WriteMessage aufgerufen wurde. Doch nur wie...

StackTrace habe ich schon verwendet, doch leider liefert der nicht immer was anständiges zurück (z.B. bei einem Konstruktor) und leider bekomme ich damit die Klasse und den Namespace nicht raus.

Daher meine Frage wie bekomme ich diese Informationen (ich will dies nicht über "strings" lösen, also einfach per drei strings die Informationen übergeben)

Vielen Dank schon mal und viele Grüße

Quaneu

1.552 Beiträge seit 2010
vor 13 Jahren

Hallo Quaneu,
mit StackTrace funktionierts auch:


StackTrace stackTrace = new StackTrace();         
StackFrame[] stackFrames = stackTrace.GetFrames(); 

foreach (StackFrame sf in stackFrames)
{
   Debug.WriteLine(sf.GetMethod().Name);                                 //Methodenname
   Debug.WriteLine(sf.GetMethod().DeclaringType.Name);                   //Klassenname
   Debug.WriteLine(sf.GetMethod().DeclaringType.Namespace);              //Namespace
   Debug.WriteLine(sf.GetMethod().DeclaringType.AssemblyQualifiedName);  //Kompletten Pfad zur Klasse
}

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

2.298 Beiträge seit 2010
vor 13 Jahren

Unabhängig davon, dass ich keine Lösung weis, da es gegen OOP verstoßen würde ein kleiner Tipp:

Dazu biete ich drei Methoden an, für Warnings, Errors und Messages.

Biete eine Methode an, die einen Status als Enum annimmt (Warning, Errors, Messages).

So vereinfachst du zum einen die Verwendung und zum anderen hast du eine Zentrale Log-Schnittstelle.

Was du intern dann machst bleibt dir überlassen.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 13 Jahren

@xxMUROxx:

Dies klappt soweit ganz gut, Danke dir. Doch leider wird eben bei einem Konstruktor immer der Methodenname ".ctor" angezeigt. Aber den bekomme ich ja dann über den KlassenNamen. Daher wäre dies eine Lösung. Vielen Dank dafür.

@inflames2k:
Vielen Dank für deinen Hinweis, habe diesen gerade umgesetzt. Wie würdest Du denn soetwas realisieren? Ich denke Du störst dich an der static class. Doch ich habe diesen Weg gewählt, da es eine zentrale Stelle geben soll, an der "geschrieben" werden kann.

5.742 Beiträge seit 2007
vor 13 Jahren

So vereinfachst du zum einen die Verwendung und zum anderen hast du eine Zentrale Log-Schnittstelle.

Das sehe ich anders:
Das Verhalten einer Methode sollte nicht von einer compiletime-Konstante abhängen - da sind mehrere Methoden IMHO durchaus die elegantere Variante.

Intern können sie ja trotzdem eine Methode aufrufen.

Zum Zugreifen auf den StackTrace: So lange das zu Logging/Debugging-Zwecken geschieht, kann ich nichts "Unsauberes" daran erkennen - lediglich den Programmablauf sollte man nicht vom Stack abhängig machen.

2.298 Beiträge seit 2010
vor 13 Jahren

Mein Logger arbeitet auch als Static. - Aber eben mit einem ENUM. Kannst ja mal anschauen. (Siehe Signatur).

Ich biete sogar nur eine Klasse an über die alles passiert (die statisch ist) und intern anhand der Konfiguration Xml-Logfile oder Windows EventLog nutzt. -> Aufrufende Methoden logge ich allerdings nicht.

@winSharp93
Naja, das ist wohl Ansichtssache.

Aber wenn ich sowieso einen Log-Eintrag schreibe, wo sich nur der Typ unterscheidet, kann ich das doch anhand des ENUM machen. - Ist jedenfalls meine Auffassung.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

5.742 Beiträge seit 2007
vor 13 Jahren

Naja, das ist wohl Ansichtssache.

Ja - durchaus.

Aber wenn ich sowieso einen Log-Eintrag schreibe, wo sich nur der Typ unterscheidet, kann ich das doch anhand des ENUM machen

Die Frage ist jedoch: Was bringt ein Enum für Vorteile im Vergleich zu einer Methode aus Aufrufersicht?
IMHO sind das kaum welche bis gar keine.

Stattdessen wird die Methode komplexer: Ein weiterer Parameter erhöht die Unübersichtlichkeit, muss validiert werden und dann in der Methode erneut geprüft.
Auch aus Aufrufersicht wird die Methode komplexer:


Logger.Log(Severity.Warning, "Person {0} not found", person.Id);
//vs:
Logger.Warning("Person {0} not found", person.Id);

Letzteres Variante ist nicht nur kürzer, es ist auch deutlich besser zu erkennen, was genau geloggt wird.

Zudem ist man besser gewappnet für zukünftige Refactorings: Angenommen, _Error_s sollen zusätzlich um einen optionalen Fehlercode erweitert werden; bei Informationsmeldungen soll dieser jedoch nicht zum Zuge kommen.
In diesem Fall würde es reichen, nur die Error-Methode zu verändern, da sie genau eine Zuständigkeit hat.

Weiteres Beispiel:
Auch im Framework existieren an vielen Stellen verschiedennamige Methoden, die man theoretisch auch zu einer zusammenfassen könnte.
So schreibt man beispielsweise:


s.ToLower(); 
s.ToLowerInvariant();
//und nicht:
s.ToLower(false);
s.ToLower(true);

//oder:
enumerable.OrderBy(p => p.Name);
enumerable.OrderByDescending(p => p.Name);
//Statt:
enumerable.OrderBy(SortOrder.Ascending, p => p.Name);
enumerable.OrderBy(SortOrder.Descending, p => p.Name);

F
10.010 Beiträge seit 2004
vor 13 Jahren

Und nochetwas, wer statische Klassen fürs logging benutzt verwehrt sich einen Umstieg und sollte sich auch mal überlegen etwas zu Architektur zu lesen.

Das benutzen eine IOC Containers ist wirklich nicht schwer und vereinfacht solche sachen echt ungemein.

H
208 Beiträge seit 2008
vor 13 Jahren

Naja...wenn man es erst einmal verstanden hat ist es wirklich einfach, aber ggf. dauert es ein bißchen **bis **man es wirklich verstanden hat... 😁 Siehe DI/IoC in der Praxis (und korrekter Aufbau der zugehörigen Klassen)

Mich würde aber sehr interessieren wie Du Logging in Verbindung mit IoC benutzt.
Klar, ich kann mir den Logger injecten lassen, aber dann habe ich ja in **jeder **Klasse die irgendwas loggen muß den ILogger im Konstruktor.

F
240 Beiträge seit 2006
vor 13 Jahren

Es gibt auch container, die das injecten über eine property zulassen, und das zumeist auch lazy, d.h. erst wenn du es brauchst. Um irgendeine Referenz auf dein Logging interface wirst du aber nicht herum kommen.

Hinweis von herbivore vor 13 Jahren

Die Hinweise, dass und wie man statische Klassen beim Logging vermeiden kann, sind jetzt ausreichend gegeben worden. Bitte nicht mehr tiefer einsteigen. Das eigentliche Thema ist ein anderes, s. Titel.