Question

I was surprised to learn that System.Diagnostics.Trace is not included in the Portable Class Library profiles. System.Diagnostics.Debug is available though.

I'm porting a library to a PCL and have typically used Trace statements to provide additional troubleshooting to consumers. For performance reasons, I want the assembly optimized so I only ship Release versions of the assembly in my NuGet package.

My understanding is that the methods for System.Diagnostics.Debug are conditionally compiled and therefore only useful when the assembly includes the DEBUG directive.

If I change my code to use System.Diagnostics.Debug and then compile in Release the approach is useless -- is there an alternative to System.Diagnostics.Trace in PCL or do I have to include the DEBUG directive in my Release build? Or is there another approach I should be considering?

Was it helpful?

Solution 2

You can specify conditional compilation directives in an individual C# file. So you can create your own wrapper around Debug.Trace, and define the DEBUG directive just for that code file, which will let you call Debug.Trace from a release DLL.

OTHER TIPS

There is a nuget package:

https://www.nuget.org/packages/System.Diagnostics.TraceSource

https://www.nuget.org/packages/System.Diagnostics.Tracing/4.0.21-beta-23516

This is Microsoft's new PCL for tracing.

Seems to be in beta so far...

I suppose the easiest way is to have a simple event in your PCL that will do nothing more than just publish appropriate eventargs (with message to be traced). Platform code can then subscribe to the event and do Trace.Write / Trace.WriteLine based on that event for you. Or you can pass a textwriter to do just logging. A rough example:

public class PclTraceWriteEventArgs:EventArgs
{
    public PclTraceWriteEventArgs(string message)
    {
        WrittenMessage = message;
    }
    public string WrittenMessage { get; private set; }
}

public class PclTrace
{
    public TextWriter LogWriter { get; private set; }

    public PclTrace(TextWriter writer)
    {
        SetTracer(writer);
    }

    public PclTrace() { }

    public void SetTracer(TextWriter writer)
    {
        LogWriter = writer;
        if (LogWriter is StreamWriter)
            (LogWriter as StreamWriter).AutoFlush = true;
    }

    public async Task WriteAsync(string message)
    {
        if (LogWriter != null) await LogWriter.WriteAsync(message);
        OnMessageWritten(new PclTraceWriteEventArgs(message));
    }

    public async Task WriteLineAsync(string message)
    {
        if(LogWriter!=null) await LogWriter.WriteLineAsync(message);
        OnMessageWritten(new PclTraceWriteEventArgs(message));
    }

    public void Write(string message)
    {
        if (LogWriter != null) LogWriter.Write(message);
        OnMessageWritten(new PclTraceWriteEventArgs(message));
    }

    public void WriteLine(string message)
    {
        if (LogWriter != null) LogWriter.WriteLine(message);
        OnMessageWritten(new PclTraceWriteEventArgs(message));
    }

    public event Action<object, PclTraceWriteEventArgs> MessageWritten;

    protected virtual void OnMessageWritten(PclTraceWriteEventArgs args)
    {
        if (MessageWritten != null)
        {
            MessageWritten(this, args);
        }
    }
}

Classes in PCL can have a (static) variable in which you instantiate the PclTrace class, and platform code can react to that:

public static class SomeClassInPCL
{   
    public static PclTrace myTracer { get; private set; }
}

And finally, do this:

class MyAwesomeClass
{
    public MyAwesomeClass()
    {
        SomeClassInPCL.myTracer.MessageWritten += TraceMessageAction;
    }
    public void TraceMessageAction(object sender, PclTraceWriteEventArgs args)
    {
        Trace.WriteLine(args.WrittenMessage);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top