add/remove TraceListener to all TraceSources
.net-3.5, c#, logging, trace, tracelistener
Solution
Based on this StackOverflow answer and this answer
Here is one way to do it:
private static void AttachToAllTraceSources(TraceListener yourListener)
{
TraceSource ts = new TraceSource("foo");
List<WeakReference> list = (List<WeakReference>)GetInstanceField(typeof(TraceSource), ts, "tracesources");
foreach(var weakReference in list)
{
if(weakReference.IsAlive)
{
TraceSource source = (weakReference.Target as TraceSource);
if(source != null && source.Name != "foo")
{
source.Listeners.Add(yourListener);
}
}
}
}
Problem
I am looking for a way to add and remove a TraceListener for all existing TraceSources. (I am not sure my approach is correct here, what other ways could I use? Basically I want to log all trace output into a file that uses the current project name as filename. Whenever a user creates or reopens a project, I want to append logs to the correct file. There can only be one project open at a time.) Code example: I create several TraceSources in my application, one for each class ``` public class Class1 { private static readonly System.Diagnostics.TraceSource trace = new System.Diagnostics.TraceSource("Class1"); } public class Class2 { private static readonly System.Diagnostics.TraceSource trace = new System.Diagnostics.TraceSource("Class2"); } ``` I now want to add or remove a traceListener to all my traceSources at Runtime, like this: ``` private System.Diagnostics.TextWriterTraceListener myListener; private onProjectOpen() { // user created a new project or opened an existing one myListener = new System.Diagnostics.TextWriterTraceListener("log-"+projectname+".log"); ALL_TRACESOURCES.Add ( myListener) ; // <-- how to do this? } private onProjectClose() { // user closed a project ALL_TRACESOURCES.Remove( myListener) ; // <-- how to do this? myListener.Flush(); myListener.Close(); myListener.Dispose(); // <-- not sure if all this is neccessary } ``` So far I found no way to do this without making all my traceSources public (seems like a bad idea) and then listing all my classes like this: ``` Class1.Trace.Add( myListener ); Class2.Trace.Add( myListener ); ... ``` which seems like a bad design choice on several levels. Or Add all my TraceSources to a custom global collection in the constructor of each class (Easy to forget / mess up; and global variables are bad ) Is there a better way? Basically I am looking for a way to set another default listener