【问题标题】:How to start a custom service in startup with dependency injection如何使用依赖注入在启动时启动自定义服务
【发布时间】:2021-06-30 16:51:23
【问题描述】:

如何从 ASP.NET Core 中的 startup.cs 启动需要依赖注入的自定义服务类?

我使用的服务是一个电报消息服务,它使用一些带有传入数据的 websocket。 我的服务:

public class TelegramService 
{
    private IUserRepository _userRepository;
    private IAsyncRepository<Coin> _coinRepository;

    public TelegramService(IUserRepository userRepository, ICoinRepository coinRepository)
    {
        _userRepository = userRepository;
        _coinRepository = coinRepository;

        this.Start();
    }

    public async Task Start()
    {
        List<User> users = await _userRepository.GetAllUsers();
        List<Coin> coins = new List<Coin>(await _coinRepository.ListAllAsync());
        foreach (var coin in coins)
        {
            TelegramMessageService telegramMessageService = new TelegramMessageService(users, coin.Type);
        }
    }

我的创业班。我做了 services.AddSingleton();但显然我错过了一些东西。

     public void ConfigureServices(IServiceCollection services)
        {
            AddSwagger(services);

            services.AddApplicationServices();
            services.AddInfrastructureServices(Configuration);
             services.AddDbContext<CryptoGuruDbContext>(options => options.UseSqlServer(configuration.GetConnectionString("CryptoGuruConnectionString"),
                b => b.MigrationsAssembly(typeof(CryptoGuruDbContext).Assembly.FullName)));

            services.AddIdentity<User, IdentityRole>()
                .AddEntityFrameworkStores<CryptoGuruDbContext>().AddDefaultTokenProviders();

            services.AddScoped(typeof(IAsyncRepository<>), typeof(BaseRepository<>));
            services.AddScoped<IUserRepository, UserRepository>();
            services.AddScoped<ICoinRepository, CoinRepository>();

            services.AddControllers();

            services.AddCors(options =>
            {
                options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
            });

            // Here is my service
            services.AddSingleton<TelegramService>();
            //services.AddTransient<TelegramService>();
            //services.AddScoped<TelegramService>();

        }

我试过AddTrasientAddScoped。两者都不会从构造函数中触发 Start() 方法。 AddSingleton 只是给出一个错误:

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: crypto_guru.Application.Services.TelegramService Lifetime: Singleton ImplementationType: crypto_guru.Application.Services.TelegramService': Cannot consume scoped service 'crypto_guru.Application.Contracts.Persistence.IUserRepository' from singleton 'crypto_guru.Application.Services.TelegramService'.)
  Source=Microsoft.Extensions.DependencyInjection
  StackTrace:
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at crypto_guru.Api.Program.<Main>d__0.MoveNext() in D:\Clouds\OneDrive\Documenten\GitHub\crypto-guru\backend\X-Copter.Api\Program.cs:line 27

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: crypto_guru.Application.Services.TelegramService Lifetime: Singleton ImplementationType: crypto_guru.Application.Services.TelegramService': Cannot consume scoped service 'crypto_guru.Application.Contracts.Persistence.IUserRepository' from singleton 'crypto_guru.Application.Services.TelegramService'.

Inner Exception 2:
InvalidOperationException: Cannot consume scoped service 'crypto_guru.Application.Contracts.Persistence.IUserRepository' from singleton 'crypto_guru.Application.Services.TelegramService'.

对不起,如果这是一个菜鸟问题,但我真的找不到做这种事情的答案。

【问题讨论】:

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


    【解决方案1】:

    问题是 TelegramService 和 IUserRepository 之间存在生命周期不匹配。 TelegramService 是一个单例并且 IUserRepository 是作用域的。如果您尝试将作用域服务注入单例,那么作用域服务本质上就变成了单例。这是captive dependency 的示例。您也应该将 TelegramService 设为范围。

    【讨论】:

      【解决方案2】:

      您不能使用生命周期较短的服务。作用域服务仅针对每个请求存在,而单例服务创建一次并共享实例。

      试试这个

       services.AddScoped<TelegramService>();
      //or you can try
       services.AddTransient<TelegramService>();
      
      

      而且我认为从构造函数运行异步方法不是一个好主意。尝试使您的启动方法无效。您所有的异步调用都转换为同步。您可以找到一些解决方法并保持异步调用,但结果仍然相同。所以最好还是用最简单的方式让一切同步。

      【讨论】:

      • 我试过这两个,但 Start() 方法不会像这样被触发。我还缺少什么吗?没有错误。
      【解决方案3】:

      它抛出此异常的原因是因为您正在创建 TelegramService 的单例实例 - services.AddSingleton&lt;TelegramService&gt;();,并且在它的构造函数中,您已注入注册为作用域的 IUserRepositoryICoinRepository

      使用任一

      services.AddScoped<IUserRepository>();
      services.AddScoped<ICoinRepository>();
      services.AddScoped<TelegramService>();
      


      services.AddSingleton<IUserRepository>();
      services.AddSingleton<ICoinRepository>();
      services.AddSingleton<TelegramService>();
      

      说明-
      TService 视为您的IUserRepository/ICoinRepository
      使用 services.AddScoped&lt;TService&gt;(); 注册服务将为每个请求创建一个 TService 实例,这意味着如果您在 3 个不同类的构造函数中注入 TService,则只会创建一个 TService 实例并将用于所有在该请求范围内进行 3 次注射。一旦该请求的范围完成,TService 实例将超出范围,并且将以类似方式为另一个请求创建新实例。
      现在将TService 视为您的TelegramService。 而services.AddSingleton&lt;TService&gt;(); 将在您的应用程序的整个生命周期内创建一个TService 实例。

      应用程序的空运行-
      现在让我们启动您的应用程序,在第一个请求期间将创建所有 3 个实例,一旦请求完成,IUserRepositoryICoinRepository 实例将超出范围,TelegramService 实例(单例)将保持没有引用IUserRepository/ICoinRepository,这是终生不匹配,这就是错误的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-23
        • 1970-01-01
        • 2015-10-28
        • 1970-01-01
        • 2016-07-02
        • 1970-01-01
        • 2018-08-01
        • 2021-12-07
        相关资源
        最近更新 更多