使用Autofac传递NLog的声明类的类型

Bal*_*ldy 4 dependency-injection nlog autofac

这个问题后,我希望autofac将声明对象的类型注入到我的NLog服务的构造函数中,以便它可以正确记录哪个类型是日志记录条目.

我的NLogService类看起来像这样......

public class NLogService : ILogService
{
    private readonly Logger _logger;

    public NLogService(Type t)
    {
        var consumerType = t.DeclaringType.FullName;
        _logger = LogManager.GetLogger(consumerType);
    }
Run Code Online (Sandbox Code Playgroud)

然而它在应用程序启动时失败,因为它显然无法解决注入NLogService的构造函数的内容,并出现以下错误...

可以使用可用的服务和参数调用在'MyProduct.Domain.Services.Logging.NLogService'类型上找到'公共绑定标志'的构造函数:无法解析构造函数'Void .ctor'的参数'System.Type t'(系统类型)'.

所以,我的问题是 - 如何指示autofac注入调用类的类型?

我试过这个......

public NLogService(Type t)
    {
        var method = MethodBase.GetCurrentMethod();
        Type consumingType = method.DeclaringType;
        var consumerType = consumingType.FullName;
        var consumerType = t.DeclaringType.FullName;
        _logger = LogManager.GetLogger(consumerType);
    }
Run Code Online (Sandbox Code Playgroud)

但我最终还是结束了 MyProduct.Domain.Services.Logging.NLogService

我想要的是进行实际日志记录的类的类型.

我已经尝试过这个建议,它对我也没有用.

ben*_*ruk 6

可以使你的NLogService通用,即NLogService<T>使用Autofac的开放式泛型支持吗?

然后你可以这样做:

public class NLogService<T> : ILogger<T>
{
    private readonly Logger _logger;
    public NLogService()
    {
        _logger = LogManager.GetLogger(typeof(T).FullName);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ven 6

使用Autofac没有真正好的方法,因为不支持"基于上下文的注入"(这是你要做的).有一个解决方法,但它不是很好......

您可以做的是恢复属性注入并为该ILogService属性定义基类或接口.例如,您可以定义以下界面:

public interface ILoggerContainer
{
    public ILogService Logger { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在需要记录器的所有类型上实现此接口:

public class Consumer : IConsumer, ILoggerContainer
{
    public ILogService Logger { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,您可以按如下方式配置Autofac:

builder.RegisterType<ILoggerContainer>()
    .OnActivating(e =>
{
    var type = typeof(LogService<>)
        .MakeGenericType(e.Instance.GetType());
    e.Instance.Logger = e.Context.Resolve(type);
});
Run Code Online (Sandbox Code Playgroud)

您可能会发现更清洁的另一种解决方法是注入ILogger<T>与父类型的类型相同的类型:

public class Consumer : IConsumer
{
    public Consumer(ILogger<Consumer> logger) { }
}
Run Code Online (Sandbox Code Playgroud)

这使得配置更容易,并且使您不必拥有基类.哪一个最合适取决于你.

正如我所说,这些是变通方法,但说实话,您可能需要重新考虑应用程序中的日志记录策略.也许你在很多地方登录.在我写的应用程序中,几乎不需要记录,当我这样做时,我会编写一个足够表达的日志消息,这样就不需要传达触发事件的类型.当您记录异常时,您将始终拥有完整的堆栈跟踪(异常记录几乎只发生在应用程序的外层,而不是在服务中).