Reputation: 301327
I have written a custom trace listener extending TextWriterTraceListener.
Now, how do I call the Dispose() on the listener? I add it through the app.config of my project.
Tried adding the call Dispose(false) in the finalizer, but it not being called. Weirdly, it is being called in VS 2010 but not when I run the application, but I know that GC collection is not guaranteed. ( basically this is being used in nunit tests to log System.Net.Socket calls from the tests and I need to do some post processing after all the tests are run and write that to the log as well. I added this part in Dispose() )
App.config snippet:
<sources>
<source name="System.Net.Sockets" tracemode="protocolonly" maxdatasize="10240">
<listeners>
<add name="CustomTraceListener" type="Tests.Custom.MyTest.CustomTraceListener, Tests.Custom.MyTest" initializeData="custom.log" />
</listeners>
</source>
</sources>
Some code snippets:
~CustomTraceListener()
{
Dispose(false);
}
protected override void Dispose (bool disposing)
{
base.Write(customProcessor.PostProcess());
base.Flush();
base.Dispose(disposing);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
Upvotes: 2
Views: 1748
Reputation: 13809
Another way to do this without reflection:
You define your tracesource somewhere, probably like this:
private static readonly TraceSource trace =
new TraceSource("System.Net.Sockets");
Now,you still need the Teardown, or something that is called at the end. Outside of unit tests, you could capture AppDomain.ProcessExit, AppDomain.UnhandledException or Window.Close
If you do not have access to the traceSource in your teardown, you can either just declare it again with new TraceSource("System.Net.Sockets");
or use another TraceSource defined in your App.config with the same shared Listeners.
Now you have 3 possibilities:
you can call trace.Close(). This will call .Close() for all traceListeners listening to that TraceSource, including your special listener
you can iterate over trace.Listeners and check the type to find your listener.
you could refer to your listener by name: trace.Listeners["CustomTraceListener"].Close()
Upvotes: 1
Reputation: 301327
I had to write a SetUpFixture and in the TearDown, used some reflection to get type "System.Diagnostics.TraceSource" from the assembly, got a private static field which was a list of all trace sources and called Dispose() on my custom listener.
FieldInfo[] info = ts.GetType().Assembly.GetType("System.Diagnostics.TraceSource").GetFields(BindingFlags.NonPublic | BindingFlags.Static);
Call Dispose() on all listeners on TraceSource
foreach (TraceListener listener in s.Listeners)
{
listener.Dispose();
Console.WriteLine("disposing");
}
Upvotes: 1
Reputation: 7152
Whatever the name of your method would be, you have to call it explicitly yourself. Doing any meaningful processing from the finalizer is very difficult because when GC destroys collected objects and it does not do it in any particular order, which means that you cannot rely on any objects you might want to deal with in your finalizer to be still alive.
Upvotes: 0