.Net Core 2.2 AutoFac 寄存器依赖项,用于注入记录器实例



工具版本

  • asp.net 核心 2.2
  • 自发法 4.9.2

问题

我正在尝试将记录器实例注入到已配置为由 Autofac 注入依赖项的类中

设置

我有一个查询数据库的类。 该类具有由 Autofac 注入到其中的连接字符串。 以下设置有效。

未注入记录器的类:

public class ItemQueries
        : IItemQueries
    {
        private readonly string _connectionString = default(string);
        public ItemQueries(string connectionString)
        {
            _connectionString = !string.IsNullOrWhiteSpace(connectionString) ? connectionString : throw new ArgumentNullException(nameof(connectionString));
        }
        public async Task<ItemViewModel> GetItemAsync(int id)
        {
            using (var connection = new SqlConnection(_connectionString))
            {
                connection.Open();
                var result = await connection.QueryAsync<dynamic>(
                    @"SELECT *                        
                    FROM dbo.items
                    WHERE Id=@id"
                    , new { id }
                );
                if (result.AsList().Count == 0)
                {
                    throw new KeyNotFoundException();
                }
                return MapItem(result.FirstOrDefault());
            }
        }
        private ItemViewModel MapItem(dynamic result)
        {
            return new ItemViewModel()
            {
                Id = result.Id,
                Name = result.Name
            };
        }
    }

这是我在Autofac注册类的方式:

public class ItemModule
        : Autofac.Module
    {
        public string QueriesConnectionString { get; }
        public ItemModule(string queriesConnectionString)
        {
            QueriesConnectionString = queriesConnectionString;
        }
        protected override void Load(ContainerBuilder builder)
        {
            builder.Register(c => new ItemQueries(QueriesConnectionString)) // <-- this breaks when I make the below changes because it's looking for an instance of ILogger<ItemQueries>
                .As<IItemQueries>()
                .InstancePerLifetimeScope();
        }
    }

但是,我想将我的 Logger 实例注入 ItemQueries 类中,所以我将其注入到构造函数中,如下所示:

private readonly ILogger<ItemQueries> _logger;
private readonly string _connectionString = default(string);
        public ItemQueries(ILogger<ItemQueries> logger, string connectionString)
        {
            _logger = logger;
            _connectionString = !string.IsNullOrWhiteSpace(connectionString) ? connectionString : throw new ArgumentNullException(nameof(connectionString));
        }

但这破坏了我的 Autofac 模块中的注册。 如何告诉 Autofac ItemQueries类需要注入记录器实例?

我认为 Autofac 能够计算出ItemQueries类需要注入ILogger<>实例(你知道,就像变魔术一样!

您可以在 lambda 注册中解决问题。这就是 lambda 中的上下文参数的用途。

builder
  .Register(c =>
    new ItemQueries(QueriesConnectionString, c.Resolve<ILogger<ItemQueries>>()))
  .As<IItemQueries>()
  .InstancePerLifetimeScope();

您需要使用Autofac的"工厂"功能。

这是使用工厂的解决方案的设置

private readonly ILogger<ItemQueries> _logger;
private readonly string _connectionString = default(string);
public delegate ItemQueries Factory(string connectionString); // --> here, you create the delegate factory
// connectionString needs to be the first parameter
public ItemQueries(string connectionString, ILogger<ItemQueries> logger) 
{
    _logger = logger;
    _connectionString = !string.IsNullOrWhiteSpace(connectionString) ? connectionString : throw new ArgumentNullException(nameof(connectionString));
}

模块设置应该是这样的:

public class ItemModule: Autofac.Module
{
    public string QueriesConnectionString { get; }
    public ItemModule(string queriesConnectionString)
    {
        QueriesConnectionString = queriesConnectionString;
    }
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<ItemQueries>();  // --> not sure if needed
        builder.Register(c => 
        {
           var factory = c.Resolve<ItemQueries.Factory>();
           return factory.Invoke(QueriesConnectionString);
        })  
        .As<IItemQueries>()
        .InstancePerLifetimeScope();
    }
}

最新更新