Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using delegates or interfaces to decouple the logging - Best practices - C#

My solutions has several projects which includes several libraries and one project for UI. Currently it is a windows forms application and I use log4net for logging. This UI project has only reference to log4net and this project maintains the configuration files. But I would like to log from my libraries as well.

Usual method for doing this is to wrap the logging calls behind an interface. Create a common project something called utilities and add this interface to this project. Now this project can be used in all the projects and can use this interface for logging.

I am thinking about an alternative design which involves passing delegates and reducing coupling and avoiding unnecessary interfaces.

Consider following class is one from my library.

public sealed class Foo
{
    Action<string> log;
    Action<string, Exception> logException;

    public Foo(Action<string> log, Action<string,Exception> logException)
    {
        this.log = log;
        this.logException = logException;
    }

    public void Work()
    {
        WL("Starting work");
        WL("Completed step1");
        .........
    }

    void WL(string message)
    {
        if(log != null) log(message);
    }

    void WL(string message, Exception exception)
    {
        if(logException != null) logException(message, exception);
    }
}

Now from the calling code, I can easily pass the logging method. Something like

Foo foo = new Foo(message => Console.WriteLine(message), 
                (message, exception) => Console.WriteLine("{0},{1}", message, exception));
foo.Work();

Used a console for explaining, in reality I will use the logging code here.

1 - Do you think this as a better solution? I think this is better as this is more loosely coupled.

2 - Is there any other better solutions available?

This is the only related question I have found here

Any thoughts...?

like image 327
Navaneeth K N Avatar asked Dec 05 '22 05:12

Navaneeth K N


2 Answers

Don't use delegates if there are multiple signatures flying in close formation. All you're doing is avoiding defining classes and interfaces that would be meaningful. log4net provides an ILog interface which is an excellent example of a simple wrapper interface you can pass in.

If you're going to use a logging framework, especially log4net, don't wrap it and don't create a single global (static OR singleton) entry point. I've written about this before, and you may be interested in the question about best practices as well.

like image 107
Jeffrey Hantin Avatar answered Dec 09 '22 14:12

Jeffrey Hantin


I have a thin layer that exposes a logging API very similar to Log4Net, that uses a provider-model design pattern to allow you to plug in any suitable logging framework. I've implemented providers for:

  • System.Diagnostics.Trace

  • log4net

  • EntLib

This means I can use logging throughout all my apps without any direct dependency on a specific logging framework, and users of my components can plug in their own favorite logging framework.

like image 37
Joe Avatar answered Dec 09 '22 14:12

Joe