Внедрение Autofa c in. NET Core 3 Console Application, внедрение IServiceProvider в класс Config (не работает?) - PullRequest
0 голосов
/ 03 марта 2020

Это может быть "глупый" вопрос, но я немного растерялся, я пытаюсь внедрить Autofa c в работающее. NET Консольное приложение Core 3.1, но, похоже, не могу получить некоторые вещи работа.

У меня есть класс с именем Config.cs, который используется в нескольких местах консольного приложения, поэтому я хотел бы сохранить этот файл, чтобы не переписывать эту реализацию.

Вот этот файл

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

Эта инъекция работает без Autofa c, но я "вынужден" реализовать ее, поскольку Autofa c используется во всех других проектах, где я работаю.

Вот 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();
    }
}

Что я делаю не так, я уверен, что чего-то не хватает или что я не правильно понял?

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Это мой образец для 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();


    }
* 1007. * и я использовал следующие пакеты:
  1. Autofa c - Version = "5.1.2"
  2. Autofa c .Extensions.DependencyInjection - Version = "6.0.0 "
1 голос
/ 03 марта 2020

Вам нужно попробовать и проверить, как это работает без модуля, измените

 builder.RegisterModule<BaseModule>();

на

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