Нет действительно хорошего способа сделать это с Autofac, потому что нет поддержки «контекстной инъекции» (что вы и пытаетесь сделать).Существует обходной путь, но он не очень ...
Что вы можете сделать, это вернуться к внедрению свойства и определить базовый класс или интерфейс для этого свойства ILogService
.Например, вы можете определить следующий интерфейс:
public interface ILoggerContainer
{
public ILogService Logger { get; set; }
}
Теперь вы можете реализовать этот интерфейс для всех типов, для которых требуется регистратор:
public class Consumer : IConsumer, ILoggerContainer
{
public ILogService Logger { get; set; }
}
С помощью этого вы можете настроить Autofacследующим образом:
builder.RegisterType<ILoggerContainer>()
.OnActivating(e =>
{
var type = typeof(LogService<>)
.MakeGenericType(e.Instance.GetType());
e.Instance.Logger = e.Context.Resolve(type);
});
Другой обходной путь, который вы можете найти более чистым, заключается в добавлении ILogger<T>
того же типа, что и тип родительского типа:
public class Consumer : IConsumer
{
public Consumer(ILogger<Consumer> logger) { }
}
Это делаетконфигурация намного проще и не позволяет иметь базовый класс.Какой из них наиболее уместен, решать только вам.
Как я уже сказал, это обходные пути, но, если честно, вам, возможно, придется пересмотреть свою стратегию ведения журналов в вашем приложении.Возможно, вы заходите в слишком много мест.В приложениях, которые я пишу, едва ли когда-либо возникает необходимость регистрироваться, и когда я это делаю, я пишу сообщение регистрации, которое достаточно выразительно, чтобы не было необходимости сообщать тип, вызвавший событие.И когда вы регистрируете исключение, у вас всегда будет полная трассировка стека (а ведение журнала исключений должно происходить почти только на внешнем уровне вашего приложения, а не в службах в любом случае).