I am configuring logging for my application and for logging I am using log4net
and castle windsor
for DI.
I want logging framework to be wrap inside custom implementation so it can be changed in future.
public interface ICustomLogger
{
void Debug(object message, Exception ex = null);
void Info(object message, Exception ex = null);
void Warn(object message, Exception ex = null);
void Error(object message, Exception ex = null);
void Fatal(object message, Exception ex = null);
}
public class CustomLogger : ICustomLogger
{
private readonly log4net.ILog _log;
private readonly log4net.ILog _log1;
public CustomLogger()
{
//approach1
var stack = new StackTrace();
var frame = stack.GetFrame(1);
var method = frame.GetMethod();
Type type = method.DeclaringType;
_log = log4net.LogManager.GetLogger(type);
//approach2
var dtype = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType;
_log1 = log4net.LogManager.GetLogger(dtype);
}
public CustomLogger(string name)
{
_log = log4net.LogManager.GetLogger(name);
}
public CustomLogger(Type type)
{
_log = log4net.LogManager.GetLogger(type);
}
public void Debug(object message, Exception ex = null)
{
if (_log.IsDebugEnabled)
{
if (ex == null)
{
_log.Debug(message);
}
else
{
_log.Debug(message, ex);
}
}
}
public void Info(object message, Exception ex = null)
{
if (_log.IsInfoEnabled)
{
if (ex == null)
{
_log.Info(message);
}
else
{
_log.Info(message, ex);
}
}
}
public void Warn(object message, Exception ex = null)
{
if (_log.IsWarnEnabled)
{
if (ex == null)
{
_log.Warn(message);
}
else
{
_log.Warn(message, ex);
}
}
}
public void Error(object message, Exception ex = null)
{
if (_log.IsErrorEnabled)
{
if (ex == null)
{
_log.Error(message);
}
else
{
_log.Error(message, ex);
}
}
}
public void Fatal(object message, Exception ex = null)
{
if (_log.IsFatalEnabled)
{
if (ex == null)
{
_log.Fatal(message);
}
else
{
_log.Fatal(message, ex);
}
}
}
}
To register this custom implementation with DI...
container.Register(Component.For<ICustomLogger>()
.ImplementedBy<CustomLogger>()
.LifeStyle.Transient);
Problem comes when I ask DI to resolve logger, then it always return logger for Customlogger
type not the class where I want to use it.
class ABC
{
ICustomLogger _logger;
public ABC(ICustomLogger logger)
{
_logger = logger; // type of this logger is CustomLogger not ABC
}
}
Both the approach are not working to resolve logger as ABC. Can anyone help me to understand what's wrong here and how to fix the issue.
You can do this via a custom dependency resolver.
You first need to create an implementation of ISubDependencyResolver
that can resolve dependencies of type ICustomLogger
:
public class LoggerResolver : ISubDependencyResolver
{
public bool CanResolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
//We can only handle dependencies of type ICustomLogger
return dependency.TargetType == typeof (ICustomLogger);
}
public object Resolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
//We pass the requested type, e.g. ABC, to the constructor of CustomLogger
return new CustomLogger(context.RequestedType);
}
}
You then need to register this resolver with the container like this:
container.Kernel.Resolver.AddSubResolver(new LoggerResolver());