工人服务问题的依赖注入

时间:2020-12-29 12:00:02

标签: .net asp.net-core signalr

首先,我应该说我一直是一个 VB.Net 爱好者程序员,所以请对 C# 保持温和!

我有一个 .NET 4.8 Windows 服务,在我的应用程序中自托管一个 SignalR 集线器,运行良好(感谢 Rick Strahl 的精彩示例)。

我想将此服务迁移到更多平台不可知的服务,.NET Core Worker Service 似乎是理想的选择,但在 Vs2019 中没有 VB.Net 模板(仅 C#),所以我正在冒险进入新领域并学习哪个有助于开发真实用例。

下面的代码基本上是嫁接了SignalR的OOTB工作服务模板的稻草人;我还没有真正掌握基础知识。

它编译正常,没有错误,但是当我尝试在 VS 中调试时,我得到了这个错误,尽管在本网站和其他网站上查找了许多这样做的例子,但它让我难倒;据我所知,我已经像其他人一样对其进行了编码,但它在 CreateHostBuilder 行上失败了?

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: ModbusWorkerService.ModbusWorker': Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.IHubContext`2[ModbusWorkerService.ModbusHub,ModbusWorkerService.IModbus]' while attempting to activate 'ModbusWorkerService.ModbusWorker'.)
  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 ModbusWorkerService.Program.Main(String[] args) in D:\Development\Comfort\Plugins\Modbus\ModbusWorkerService\Program.cs:line 12

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

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: ModbusWorkerService.ModbusWorker': Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.IHubContext`2[ModbusWorkerService.ModbusHub,ModbusWorkerService.IModbus]' while attempting to activate 'ModbusWorkerService.ModbusWorker'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.IHubContext`2[ModbusWorkerService.ModbusHub,ModbusWorkerService.IModbus]' while attempting to activate 'ModbusWorkerService.ModbusWorker'.

这可能是我在 c# 方面的经验不足(因为 VB.Net 中的 DI 对我来说是第二天性),但任何人都可以就我做错的事情向我提供任何指导。

代码如下。

问候

朱利安


这里是 Program.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ModbusWorkerService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args)
                .Build().Run();
        
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<ModbusWorker>();
                });
    }

    public class Startup
    {
        public static void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
            services.AddHostedService<ModbusWorker>();

        }

        public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<ModbusHub>("/hubs/Modbus");
            });
        }
    }
}

这是我的工作人员:

using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ModbusWorkerService
{
    public class ModbusWorker : BackgroundService
    {
        private readonly ILogger<ModbusWorker> _logger;
        private readonly IHubContext<ModbusHub, IModbus> _ModbusHub;

        public ModbusWorker(ILogger<ModbusWorker> logger, IHubContext<ModbusHub, IModbus> ModbusHub)
        {
            _logger = logger;
            _ModbusHub = ModbusHub;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await _ModbusHub.Clients.All.ShowTime(DateTime.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

最后是我的 SignalR 集线器:


using System;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.SignalR;

namespace ModbusWorkerService
{
    public class ModbusHub : Hub<IModbus>
    {
        public static ConcurrentDictionary<string, string> ConnectedUsers = new ConcurrentDictionary<string, string>();
       //public static BackgroundService HubHost;

        [HubMethodName("SendMessage")]
        public async Task SendMessage(string user)
        {
            await Clients.All.SendAsync("ReceiveGreeting", $"Good Morning {user}");
        }

        public override async Task OnConnectedAsync()
        {
            string ClientID = GetClientID();
            string HostName = GetHostName();

            if (!ConnectedUsers.ContainsKey(ClientID))
                ConnectedUsers.TryAdd(ClientID, HostName);

            // Clients.All.ShowUsersOnLine(ConnectedUsers.Count);

            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {
            string ClientID = GetClientID();

            if (ConnectedUsers.ContainsKey(ClientID))
                ConnectedUsers.TryRemove(ClientID, out _);

            // Clients.All.ShowUsersOnLine(ConnectedUsers.Count);

            await base.OnDisconnectedAsync(exception);
        }

        private string GetClientID()
        {
            string ClientID = "";
            //if (!(Context.QueryString['ClientID'] == null))
            //    // ClientID passed from application 
            //    ClientID = Context.QueryString['ClientID'].ToString();

            if (ClientID.Trim() == "")
                ClientID = Context.ConnectionId;

            return ClientID;
        }

        private string GetHostName()
        {
            string HostName = "";
            //if (!(Context.QueryString['HostName'] == null))
            //    // ClientID passed from application 
            //    HostName = Context.QueryString['HostName'].ToString();

            if (HostName.Trim() == "")
                HostName = "Not Known";
            return HostName;
        }

    }

    public interface IModbus
    {
        Task ShowTime(DateTime currentTime);

        Task SendAsync(string Method, string Values);
    }
}

1 个答案:

答案 0 :(得分:0)

我想你忘记使用启动了。

替换 program.cs 中的以下几行

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<ModbusWorker>();
            });

public static IHostBuilder CreateWebHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
相关问题