I'm new to Autofac and am trying to resolve an interface using a factory but can't seem to find the relevant part in the documentation to get this working.
I have the following interfaces to abstract the logging implementation:
public interface ILog
{
void Info(string message);
void Debug(string message);
void Error(string message, Exception exception = null);
}
public interface ILogFactory
{
ILog GetLogger(Type type);
}
And then the following implementations of these interfaces:
public class Log : ILog
{
private readonly Action<string> _logDebug;
private readonly Action<string, Exception> _logError;
private readonly Action<string> _logInfo;
public Log(Action<string> logInfo, Action<string> logDebug, Action<string, Exception> logError)
{
_logDebug = logDebug;
_logInfo = logInfo;
_logError = logError;
}
public void Debug(string message)
{
_logInfo(message);
}
public void Error(string message, Exception exception = null)
{
_logError(message, exception);
}
public void Info(string message)
{
_logInfo(message);
}
}
public class Log4NetLogFactory : ILogFactory
{
public Log4NetLogFactory()
{
XmlConfigurator.Configure();
}
public ILog GetLogger(Type type)
{
var logger = LogManager.GetLogger(type);
return new Log(logger.Info, logger.Debug, logger.Error);
}
}
I'm stuck with how to resolve ILog in Autofac using ILogFactory. I've registered a singleton for ILogFactory with:
builder.RegisterType<Log4NetLogFactory>().As<ILogFactory>().SingleInstance();
but I'm not sure how to resolve the ILog interface using the GetLogger method of ILogFactory passing in the caller Type.
It would appear that I need to something like this:
builder.Register((c, p) => c.Resolve<ILogFactory>().GetLogger(??Caller Type Here??)).As<ILog>();
But I'm not sure how to get the caller type into the GetLogger constructor.
I managed to get this working thanks to this answer. This is the module I ended up with:
public class LoggingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Log4NetLogFactory>().As<ILogFactory>().SingleInstance();
builder.Register((c, p) => c.Resolve<ILogFactory>().GetLogger(p.TypedAs<Type>()));
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing +=
(sender, args) =>
{
var forType = args.Component.Activator.LimitType;
var logParameter = new ResolvedParameter(
(p, c) => p.ParameterType == typeof(ILog),
(p, c) => c.Resolve<ILog>(TypedParameter.From(forType)));
args.Parameters = args.Parameters.Union(new[] { logParameter });
};
}
}
This can be registered in the container with:
builder.RegisterModule(new LoggingModule());