【问题标题】:asp.net core AppSettings fail when used inside hosted service在托管服务中使用时,asp.net core AppSettings 失败
【发布时间】:2019-05-14 08:45:40
【问题描述】:

我有以下几点:

   public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    .ConfigureServices(services => services.AddAutofac());

public class HostedServiceA : IHostedService
{
    private readonly AppSettings appSettings;

    public HostedServiceA(AppSettings appSettings)
    {
        this.appSettings = appSettings;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddHttpClient();

    services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

    services.AddHostedService<HostedServiceA>();
}

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterType<SomeService>().As<ISomeService>().SingleInstance();
}

我正在使用 autofac。当我尝试运行时,出现异常并且程序无法启动:AppSettings 也在另一个服务中使用。当我从 HostedService 中删除 AppSettings 时,它可以工作。

Unhandled Exception: Autofac.Core.DependencyResolutionException: An exception was thrown while activating Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor -> ?:Microsoft.Extensions.Hosting.IHostedService[] -> Test.MicroService.MicroServices.Web.HostedServices.RatesHostedService. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Test.MicroService.MicroServices.Web.HostedServices.RatesHostedService' can be invoked with the available services and parameters:
Cannot resolve parameter 'Test.MicroService.MicroServices.Infrastructure.AppSettings appSettings' of constructor 'Void .ctor(Test.MicroService.MicroServices.Infrastructure.AppSettings)'.                                            at Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext context, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Activators\Reflection\ReflectionActivator.cs:line 160
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Activators\Reflection\ReflectionActivator.cs:line 120
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget) in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 118
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget) in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 136
   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator) in C:\projects\autofac\src\Autofac\Core\Lifetime\LifetimeScope.cs:line 306
   at Autofac.Core.Resolving.InstanceLookup.Execute() in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 85
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Resolving\ResolveOperation.cs:line 130                                                                                                                                                                                                                                 at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Resolving\ResolveOperation.cs:line 83
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) in C:\projects\autofac\src\Autofac\ResolutionExtensions.cs:line 1041
   at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\ResolutionExtensions.cs:line 871
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)

我做错了什么?

【问题讨论】:

  • 该错误没有说明appsettings 文件。它抱怨您自己的自定义 Test.MicroService.MicroServices.Infrastructure.AppSettings 类没有在 DI 容器中注册,或者找不到
  • @PanagiotisKanavos 我已经完成了``` services.Configure(Configuration.GetSection("AppSettings"));```。我编辑了我的原始帖子并补充说,当我在其他地方使用 AppSettings 时,它可以正常工作。当我在 HostedService 中添加它时它不起作用
  • 然而,这就是错误所抱怨的。你配置Autofac了吗?你的Main 是什么样的?它应该包含.ConfigureServices(services =&gt; services.AddAutofac()) 之前 .UseStartup&lt;Startup&gt;()
  • 已注册。编辑我的初始帖子以添加注册 autofac 的代码
  • 虽然顺序不对

标签: c# .net asp.net-core autofac


【解决方案1】:

托管服务在单独的线程上运行。 DI 按线程工作,您需要执行以下操作:

public MyHostedService(IServiceScopeFactory serviceScopeFactory)
            : base(consumer)
        {
            _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));

        }

And inside the method use like this:

using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var storageService = scope.ServiceProvider.GetRequiredService<MyService>();

}

【讨论】:

  • 根本不需要,也无济于事。配置和 DI 在启动时进行配置。托管服务只不过是带有一些特殊生命周期处理的 Singleton 服务
  • 答案的代码解决了一个不同的问题——如何使用像托管服务一样的单例服务中的作用域服务。如果服务一开始就没有注册,那根本没有帮助
【解决方案2】:

很可能没有配置 Autofac,或者配置没有出现在正确的位置。

该错误抱怨 Autofac 找不到 Test.MicroService.MicroServices.Infrastructure.AppSettings 类,即使调用了

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

此调用将向当前 DI 容器注册 AppSettings 类。这意味着必须在任何尝试注册服务之前配置 DI 容器。

var host = new WebHostBuilder()
    .UseKestrel()
    .ConfigureServices(services => services.AddAutofac())
    ....
    .UseStartup<Startup>()
    .Build();

【讨论】:

  • 它已注册。编辑我的初始帖子以添加注册 autofac 的代码。正如我所说,everyrthing 没有任何问题。当我将 AppSettings 添加到 HostedService 时出现问题。
  • @pantonis 的顺序是错误的。 DI 容器必须调用UseStartup 之前添加。否则使用 ASP.NET Core DI 容器。添加Autofac不会重新注册任何已经注册到内置容器的服务
  • 你指的是哪个顺序?
猜你喜欢
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 1970-01-01
  • 2019-07-23
相关资源
最近更新 更多