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

c#, delegates, interface

Solution

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.

Problem

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...?

Original source