I have been investigating ways to inject the Log4Net ILog into classes using Castle Windsor. In most examples, I see where Castle Windsor can provide a "facilitator" that provides property injection, and injects the ILogger (not ILog). I have found only one example where contructor injection is used, and the facilitator method is not used (see Castle Windsor dependency injection: Use the caller type as a parameter)
In all these examples, it seems Log4Net wants to have a named logger. Most examples refer to the Log4Net static method LogManager.GetLogger(class name here). This makes it a challenge to define the dependancies for CastleWindsor without using reflection, or the facilitator method (can facilitator method be used with ctor injection???). When looking at the question by Ilya Kogan (URL above...), I guess I don't understand why I need, or even want a named logger. Can't I use a logger by the same name everywhere?
For example, can't I just register the logger with hardcoded name of XXX? (It seems to work fine, and in the end, I just want to log - I don't care which logger logged it...) Is there a scope issue? Is there a memory leak issue? Why can't/shouldn't the logger be a singleton?
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<log4net.ILog>().UsingFactoryMethod(() => log4net.LogManager.GetLogger("xxx"))
);
}
UPDATE:
Upon some research, a hardcoded named logger can be used - such as XXX in my example above, but if the configuration of the logger outputs the logger name to the logfile and if the logger name is dynamically assigned to the same name as the method or class, you automagically get reference to where the logging originated from. Context within the log file can be very helpful.
When specifically addressing ctor injection, there seems to be 5 possible options...
The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets. log4net is a port of the excellent Apache log4j™ framework to the Microsoft® . NET runtime. We have kept the framework similar in spirit to the original log4j while taking advantage of new features in the .
You can configure the log4net. config file to create log files. The file is located in the webroot\App_data directory of the installation. The different log files are described in Services logs.
Log4net is a logging utility for . NET applications. It's based on log4j, which is for Java applications. Log4net is highly configurable, so you can use it in many scenarios.
Good questions.
In short, log4net wants named loggers because then the names are used for filtering the log output (see the log4net documentation for details). Type name is just a convenient convention as it provides you that extra bit of context and coupled with correct use of namespaces allows you do things like say "log all NHibernate messages to a separate file"
That's also why commonly, if you're not using container for that, you have a single, static logger property/field in your classes.
The ILogger
you're referring to is the abstraction in Castle over logging, one of which can be for log4net.
While the LoggingFacility
provides out of the box support for providing dependencies on ILogger
it is by no means forcing you to do this.
Your ILog
registration should be rewritten as follows (I'm writing this from memory so details may be slightly different):
Component.For<log4net.ILog>()
.UsingFactoryMethod((k, c) => log4net.LogManager.GetLogger(c.RequestedType))
.LifestyleTransient()
c.RequestedType
will give you the type for which you're satisfying the dependency and making it transient will avoid the issue that all types would reuse the single instance of logger named after whatever the first type to request the dependency was.
The recommended way to DI an Log4Net Log using Castle Windsor is to use Facilities. One has already been created for Log4Net and its use is demonstrated in this tutorial.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With