在 .NET Core 3 控制台应用程序中实施 Autofac,将 IServiceProvider 注入 Config class(不工作?)

Implementing Autofac in .NET Core 3 Console Application, injecting IServiceProvider into Config class (not working?)

这可能是一个 "stupid" 问题,但我有点迷路了,我正在尝试将 Autofac 实现到一个工作的 .NET Core 3.1 控制台应用程序中,但似乎无法让某些东西工作.

我有一个名为 Config.cs 的 class 在控制台应用程序的多个地方使用,所以我想保留该文件以免重写此实现。

这是那个文件

public class Config : IConfig
{
    readonly IConfiguration _config;

    public Config(IServiceProvider services)
    {
        _config = (IConfiguration)services.GetService(typeof(IConfiguration));
    }

    public string StorageConnectionString => _config["ConnectionStrings:StorageConnectionString"];
    public string SqlConnectionString => _config["ConnectionStrings:SqlConnectionString"];
    public string MongoConnectionString => _config["ConnectionStrings:MongoConnectionString"];
    public string RayGunApiKey => _config["RayGunApiKey"];
    public string ElasticsearchUri => _config["Uris:ElasticsearchUri"];
    public string StatsDUri => _config["Uris:StatsDUri"];

    public string Get(string key) => _config[key];
}

这个第一次用在Functions.cs的TimeTrigger中:

public class Functions
{
    readonly IConfig _config;

    public Functions(ILogger<Functions> logger, IConfig config)
    {
        _logger = logger;
        _config = config;
    }


    public void Run([TimerTrigger("00:00:01", RunOnStartup = true, UseMonitor = true)]TimerInfo myTimer)
    {
        ...
    }
}

但是当我启动控制台应用程序时抛出错误

System.InvalidOperationException: Unable to resolve service for type 'DataPurger.IConfig' while attempting to activate 'DataPurger.Functions'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider serviceProvider) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 37
   at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 32
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 20
   at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 26
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 44
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 846
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 117

此注入无需 Autofac 即可工作,但我"forced" 实施它,因为我工作的所有其他项目都使用了 Autofac。

这是Program.cs

static void Main(string[] args)
{
    RegisterServices();

    CreateHostBuilder(args).Build().RunAsync().Wait();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            config.AddEnvironmentVariables();
            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true,
                reloadOnChange: true);
        })
        .ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        })
        .ConfigureServices(s =>
        {
            s.AddLogging();
            s.AddOptions();
        })
        .ConfigureWebJobs(builder =>
        {
            builder.AddAzureStorageCoreServices();
            builder.AddExecutionContextBinding();
            builder.AddTimers();
        })
        .UseConsoleLifetime()
        .UseServiceProviderFactory(new AutofacServiceProviderFactory());

static void RegisterServices()
{
    var collection = new ServiceCollection();
    var builder = new ContainerBuilder();

    builder.RegisterModule<BaseModule>();
    builder.Populate(collection);

    var container = builder.Build();

    _serviceProvider = new AutofacServiceProvider(container);
}

public class BaseModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<Config>().As<IConfig>().SingleInstance();
    }
}

我哪里做错了,我肯定有什么地方遗漏了,或者我没有理解正确?

您需要尝试检查它在没有模块的情况下如何工作,更改

 builder.RegisterModule<BaseModule>();

builder.RegisterType<Config>().As<IConfig>().SingleInstance();

这是我的 ASP .Net core 3.1
样本 在 Program.cs 我改变了

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<-like yours
            .UseSerilog()
            .ConfigureLogging((context, builder) => builder.AddSerilog())
            .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });

我添加到 Startup.cs

public void ConfigureContainer(ContainerBuilder builder)
    {
        builder.RegisterType<QuartzWrapper>().As<IQuartzWrapper>().SingleInstance();
        builder.Register(provider => new JobFactory(provider)).As<IJobFactory>().InstancePerDependency();
        builder.RegisterType<JobClass>().As<IJob>().InstancePerDependency();


    }

我使用了下一个包:

  1. Autofac - 版本="5.1.2"
  2. Autofac.Extensions.DependencyInjection - 版本="6.0.0"