简体   繁体   中英

Resolve interface from Factory using Autofac

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM