SOLID principles state in the Dependency Inversion Principle that you should depend upon abstractions, not implementations. With that in mind, services should not be creating instances of log4net loggers, rather depending on an abstraction of that service. However, creation of a log4net logger requires the type to be passed in when it is instantiated. For some IoC containers which allow service location (and if you don’t strictly adhere to IoC principles), this is fine as you can locate the service whilst passing a parameter into the constructor. Using constructor injection with a container such as Autofac however, means you need to rely on the dependency to be passed correctly.
The Log Service
I created an iterface for a log service which currently implements ILog from the log4net library. I can at some point however, simply copy these declarations into my ILogService interface if I decide to use something other than log4net. Below is the implementation of the LogService (or part of it, the whole implementation is huge!). It takes a generic type, which it then passes into the logger when it is created.
Configuring the container
Register the service with the container as an open generic (the type asked for in the interface will be passed to the concrete).
Using the log service
Introduce and initialize the service in the constructor (pass in the type of the class where you’re using the log service, in this case the HomeController). Then simply call the service in the same way that you’d call log4net.
There’s a few benefits in using this log service rather than using an instance of log4net itself. If at any point you change logging frameworks, assuming there’s similar methods (debug, warn, info etc) then you can simply switch it out in the log service itself, rather than every place you’ve used the logger. You can unit test and ensure a class that you’re testing is logging (and at the correct points) by mocking the interface.
Hope this helps.