首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用简单注入器在webjob作业中创建IHubContext<MyClass>实例

使用简单注入器在webjob作业中创建IHubContext<MyClass>实例
EN

Stack Overflow用户
提问于 2019-11-30 06:09:12
回答 1查看 509关注 0票数 1

我正在使用WebCore2.2和SignalR核心,我需要在我的.NET工作中通过简单注入器注入IHubContext<MyClass>

它在我的web应用程序中工作得很好,但当我试图通过web作业访问我的服务时,它抱怨缺少IHubContext<IHubContext<BroadcastHub>>注入

我需要一种通过简单的Injector注册它的方法

这是我的Webjob作业中Program.cs文件中的Configuration

代码语言:javascript
运行
复制
using AutoMapper;
using Gateway.BLL.BaseClasses;
using Gateway.BLL.Config;
using Gateway.BLL.Services;
using Gateway.BLL.Services.Interfaces;
using Gateway.BLL.SignalR;
using Gateway.Model.MappingProfiles;
using Gateway.Repository;
using Gateway.Repository.Interfaces;
using Gateway.Repository.Repositories;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Internal;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SimpleInjector;
using System;
using System.IO;
using System.Net.Http;

namespace Gateway.WebJob
{
    class Program
    {
        private static void Main()
        {
            var container = new Container();

            DbContextOptionsBuilder ob = new DbContextOptionsBuilder();

            var config = new MapperConfiguration
                (cfg =>
            {
                cfg.AddProfile(new ModelMappingProfile());
            }
                );
            var mapper = config.CreateMapper();

            var loggerFactory = new LoggerFactory();

            ServiceCollection sr = new ServiceCollection();

            sr.AddSignalR();


            var serviceProvider = sr.AddHttpClient().BuildServiceProvider();
            var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();

            IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
            // Duplicate here any configuration sources you use.
            configurationBuilder.AddJsonFile("appsettings.json");
            IConfiguration configuration = configurationBuilder.Build();

            var medchartApiConfiguration = new MedchartApiConfiguration();
            configuration.Bind("MedchartApiConfiguration", medchartApiConfiguration);

            var serviceBusConfiguration = new ServiceBusConfiguration();
            configuration.Bind("ServiceBusConfiguration", serviceBusConfiguration);

            ob = ob.UseSqlServer(configuration["ConnectionString:GatewayDB"]);

            IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());

            ConfigureServices(sr);

            var builder = new HostBuilder();
            builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddServiceBus(o =>
                {
                    o.MessageHandlerOptions.AutoComplete = true;
                    o.MessageHandlerOptions.MaxConcurrentCalls = 10;
                    o.ConnectionString = "Endpoint=sb://gatewayqueue.servicebus.windows.net/;SharedAccessKeyName=admin;SharedAccessKey=Wd2YwCEJT2g3q4ykvdOIU2251YD5FizCn5aCuumzdz4=";
                }).AddSignalR();
            });
            builder.ConfigureLogging((context, b) =>
            {
                b.AddConsole();
                string instrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
                if (!string.IsNullOrEmpty(instrumentationKey))
                {
                    b.AddApplicationInsightsWebJobs(o => o.InstrumentationKey = instrumentationKey);
                }
            });

            builder.ConfigureServices((hostContext, services) => {
                //services.AddHttpClient();
                //hostContext.Configuration.Bind("MedchartApiConfiguration", medchartApiConfiguration);
                //services.AddSingleton(medchartApiConfiguration);
                services.AddSingleton(container);
                services.AddScoped<JobActivator.ScopeDisposable>();
                services.AddScoped<IJobActivator, JobActivator>();
            });

            container.Register<IPatientService, PatientService>();
            container.Register<IPatientRepository, PatientRepository>();
            container.Register<IProviderService, ProviderService>();
            container.Register<IPatientGroupProviderRepository, PatientGroupProviderRepository>();
            container.Register<IPatientGroupRepository, PatientGroupRepository>();
            container.Register<IConsentRepository, ConsentRepository>();
            container.Register<IHttpClientWrapper, HttpClientWrapper>();
            container.Register<IMedchartService, MedchartService>();
            container.Register<IGroupRepository, GroupRepository>();
            container.Register<IReportRepository, ReportRepository>();
            container.Register<IProviderRepository, ProviderRepository>();
            container.RegisterSingleton(httpClientFactory);
            container.RegisterSingleton(memoryCache);
            container.RegisterSingleton(medchartApiConfiguration);
            container.RegisterSingleton(serviceBusConfiguration);
            container.Register<ILoggerFactory>(() => loggerFactory, Lifestyle.Singleton);
            container.RegisterSingleton(configuration);
            container.RegisterSingleton(typeof(ILogger<PatientRepository>), typeof(Logger<PatientRepository>));
            container.RegisterSingleton(typeof(ILogger<PatientService>), typeof(Logger<PatientService>));
            container.RegisterSingleton(typeof(ILogger<HttpClientWrapper>), typeof(Logger<HttpClientWrapper>));
            container.RegisterSingleton(typeof(ILogger<MedchartService>), typeof(Logger<MedchartService>));
            container.RegisterSingleton(typeof(ILogger<ProviderService>), typeof(Logger<ProviderService>));
            container.RegisterSingleton(typeof(ILogger<ProviderRepository>), typeof(Logger<ProviderRepository>));
            container.RegisterSingleton(typeof(ILogger<ReportRepository>), typeof(Logger<ReportRepository>));
            container.RegisterSingleton(mapper);
            container.Register<GatewayDBContext>(() => {
                var options = ob.Options;
                return new GatewayDBContext(options);
            });

            var host = builder.Build();
            using (host)
            {
                host.Run();
            }
        }

        private static IConfiguration Configuration { get; set; }
        private static void ConfigureServices(IServiceCollection services)
        {
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

            Configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();

            services.AddSingleton(Configuration);
            services.AddTransient<Functions, Functions>();
            services.AddLogging(builder => builder.AddConsole());
        }
    }
}

这是我使用SignalR的简化服务:(这是webjob将使用它的另一个项目

代码语言:javascript
运行
复制
using Microsoft.AspNetCore.SignalR;
using Gateway.BLL.SignalR;

// namespace Gateway.BLL.Services
public class PatientService : HttpClientWrapper, IPatientService
{
    private readonly IHubContext<BroadcastHub> _hubContext;

    public PatientService(IHubContext<BroadcastHub> hubContext)
        : base(logger,httpClientFactory,medchartConfig)
    {
        _hubContext = hubContext;
    }

    public async Task<OutputHandler<IEnumerable<PatientEnrollmentParams>>>
        CreatePatientAsync(List<PatientEnrollmentParams> patients,
            CancellationToken ct)
    {
        var result = new OutputHandler<IEnumerable<PatientEnrollmentParams>>();
        await _hubContext.Clients.All.SendAsync("BroadcastMessage");
        return result;
    } 
}

这是我的webjob作业,它将调用另一个项目中的PatientService

代码语言:javascript
运行
复制
    using Gateway.BLL.Config;
using Gateway.BLL.Processors;
using Gateway.BLL.Queues;
using Gateway.BLL.Services;
using Gateway.Model.Queues;
using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SimpleInjector;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Gateway.WebJob
{
    public class Functions
    {
        private Container _container;
        public Functions(Container container)
        {
            _container = container;
        }

        public async Task ProcessEnrollmentStatus([ServiceBusTrigger("%ServiceBusConfiguration:EnrollmentMessage:QueueName%")]string message, ILogger log)
        {
            var _patientService = _container.GetInstance<IPatientService>();
            GetEnrollmentStatusTaskProcessor processor = new GetEnrollmentStatusTaskProcessor(_patientService);
            EnrollmentStatusTask data = JsonConvert.DeserializeObject<EnrollmentStatusTask>(message);
            await processor.Process(data);
        }

        public async Task ProcessConsentRequestStatus([ServiceBusTrigger("%ServiceBusConfiguration:ConsentRequestMessage:QueueName%")]string message, ILogger log)
        {
            var _patientService = _container.GetInstance<IPatientService>();
            GetConsentRequestTaskProcessor processor = new GetConsentRequestTaskProcessor(_patientService);
            ConsentRequestTask data = JsonConvert.DeserializeObject<ConsentRequestTask>(message);
            await processor.Process(data);
        }
    }
}

下面是将调用patientService的进程方法:

代码语言:javascript
运行
复制
    using Gateway.BLL.Services;
using Gateway.Model.Queues;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Gateway.BLL.Processors
{
    public class GetEnrollmentStatusTaskProcessor :  IProcessor<EnrollmentStatusTask>
    {
        private IPatientService _patientService;

        public GetEnrollmentStatusTaskProcessor(IPatientService patientService)
        {
            _patientService = patientService;
        }

        public async Task<bool> Process(EnrollmentStatusTask data)
        {
            bool updated = await _patientService.UpdatePatientEnrollmentStatus(data.PatientId, data.PatientMedchartId.ToString(), data.GroupId);
            return updated;
        }
    }
}

我需要在program.cs的ways作业中注册IHubContext<MyClass>,但我无法通过以下方式注册它:

代码语言:javascript
运行
复制
hubContext = serviceProvider.GetService<IHubContext<BroadcastHub>>();
container.RegisterSingleton(hubContext);

或者这样

代码语言:javascript
运行
复制
container.Register<IHubContext<BroadcastHub>>(Lifestyle.Singleton);

更新2019-12-02:我能够解决IHubContext问题,但现在我收到了新问题。这是我的函数类:

代码语言:javascript
运行
复制
    using Gateway.BLL.Config;
using Gateway.BLL.Processors;
using Gateway.BLL.Queues;
using Gateway.BLL.Services;
using Gateway.Model.Queues;
using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SimpleInjector;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Gateway.WebJob
{
    public class Functions
    {
        private Container _container;
        public Functions(Container container)
        {
            _container = container;
        }

        public async Task ProcessEnrollmentStatus([ServiceBusTrigger("%ServiceBusConfiguration:EnrollmentMessage:QueueName%")]string message, ILogger log)
        {
            var _patientService = _container.GetInstance<IPatientService>();
            GetEnrollmentStatusTaskProcessor processor = new GetEnrollmentStatusTaskProcessor(_patientService);
            EnrollmentStatusTask data = JsonConvert.DeserializeObject<EnrollmentStatusTask>(message);
            await processor.Process(data);
        }

        public async Task ProcessConsentRequestStatus([ServiceBusTrigger("%ServiceBusConfiguration:ConsentRequestMessage:QueueName%")]string message, ILogger log)
        {
            var _patientService = _container.GetInstance<IPatientService>();
            GetConsentRequestTaskProcessor processor = new GetConsentRequestTaskProcessor(_patientService);
            ConsentRequestTask data = JsonConvert.DeserializeObject<ConsentRequestTask>(message);
            await processor.Process(data);
        }
    }
}

这是我所有更新后的progrm.cs类:

代码语言:javascript
运行
复制
    using AutoMapper;
using Gateway.BLL.BaseClasses;
using Gateway.BLL.Config;
using Gateway.BLL.Services;
using Gateway.BLL.Services.Interfaces;
using Gateway.BLL.SignalR;
using Gateway.Model.MappingProfiles;
using Gateway.Repository;
using Gateway.Repository.Interfaces;
using Gateway.Repository.Repositories;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Internal;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SimpleInjector;
using System;
using System.IO;
using System.Net.Http;

namespace Gateway.WebJob
{
    class Program
    {
        private static void Main()
        {
            var container = new Container();

            DbContextOptionsBuilder ob = new DbContextOptionsBuilder();

            var config = new MapperConfiguration
                (cfg =>
            {
                cfg.AddProfile(new ModelMappingProfile());
            }
                );
            var mapper = config.CreateMapper();

            var loggerFactory = new LoggerFactory();

            ServiceCollection sr = new ServiceCollection();
            sr.AddLogging();
            sr.AddSignalR();

            sr.AddDbContextPool<GatewayDBContext>(options => { /*options */ });

            sr.AddSimpleInjector(container, options =>
             {
                 options.AddLogging();
                 //options.CrossWire<ILoggerFactory>();
             });

            sr.BuildServiceProvider(validateScopes: true).UseSimpleInjector(container);


            var serviceProvider = sr.AddHttpClient().BuildServiceProvider();
            var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();

            IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
            // Duplicate here any configuration sources you use.
            configurationBuilder.AddJsonFile("appsettings.json");
            IConfiguration configuration = configurationBuilder.Build();

            var medchartApiConfiguration = new MedchartApiConfiguration();
            configuration.Bind("MedchartApiConfiguration", medchartApiConfiguration);

            var serviceBusConfiguration = new ServiceBusConfiguration();
            configuration.Bind("ServiceBusConfiguration", serviceBusConfiguration);

            ob = ob.UseSqlServer(configuration["ConnectionString:GatewayDB"]);

            IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());

            ConfigureServices(sr);

            var builder = new HostBuilder();
            builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddServiceBus(o =>
                {
                    o.MessageHandlerOptions.AutoComplete = true;
                    o.MessageHandlerOptions.MaxConcurrentCalls = 10;
                    o.ConnectionString = "Endpoint=sb://gatewayqueue.servicebus.windows.net/;SharedAccessKeyName=admin;SharedAccessKey=Wd2YwCEJT2g3q4ykvdOIU2251YD5FizCn5aCuumzdz4=";
                });
            });
            builder.ConfigureLogging((context, b) =>
            {
                b.AddConsole();
                b.Services.AddLogging();
                string instrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
                if (!string.IsNullOrEmpty(instrumentationKey))
                {
                    b.AddApplicationInsightsWebJobs(o => o.InstrumentationKey = instrumentationKey);
                }
            });

            builder.ConfigureServices((hostContext, services) =>
            {
                //services.AddHttpClient();
                //hostContext.Configuration.Bind("MedchartApiConfiguration", medchartApiConfiguration);
                //services.AddSingleton(medchartApiConfiguration);
                //services.AddSingleton(container);
                //services.AddScoped<JobActivator.ScopeDisposable>();
                //services.AddScoped<IJobActivator, JobActivator>();
            });

            container.Register<IPatientService, PatientService>();
            container.Register<IPatientRepository, PatientRepository>();
            container.Register<IProviderService, ProviderService>();
            container.Register<IPatientGroupProviderRepository, PatientGroupProviderRepository>();
            container.Register<IPatientGroupRepository, PatientGroupRepository>();
            container.Register<IConsentRepository, ConsentRepository>();
            container.Register<IHttpClientWrapper, HttpClientWrapper>();
            container.Register<IMedchartService, MedchartService>();
            container.Register<IGroupRepository, GroupRepository>();
            container.Register<IReportRepository, ReportRepository>();
            container.Register<IProviderRepository, ProviderRepository>();
            container.RegisterSingleton(httpClientFactory);
            container.RegisterSingleton(memoryCache);
            container.RegisterSingleton(medchartApiConfiguration);
            container.RegisterSingleton(serviceBusConfiguration);
            //container.Register<ILoggerFactory>(() => loggerFactory, Lifestyle.Singleton);
            container.RegisterSingleton(configuration);
            container.RegisterSingleton(typeof(ILogger<PatientRepository>), typeof(Logger<PatientRepository>));
            container.RegisterSingleton(typeof(ILogger<PatientService>), typeof(Logger<PatientService>));
            container.RegisterSingleton(typeof(ILogger<HttpClientWrapper>), typeof(Logger<HttpClientWrapper>));
            container.RegisterSingleton(typeof(ILogger<MedchartService>), typeof(Logger<MedchartService>));
            container.RegisterSingleton(typeof(ILogger<ProviderService>), typeof(Logger<ProviderService>));
            container.RegisterSingleton(typeof(ILogger<ProviderRepository>), typeof(Logger<ProviderRepository>));
            container.RegisterSingleton(typeof(ILogger<ReportRepository>), typeof(Logger<ReportRepository>));
            container.RegisterSingleton(mapper);
            //container.Register<GatewayDBContext>(() =>
            //{
            //    var options = ob.Options;
            //    return new GatewayDBContext(options);
            //});
            container.Verify();
            var host = builder.Build();
            using (host)
            {
                host.Run();
            }
        }

        private static IConfiguration Configuration { get; set; }
        private static void ConfigureServices(IServiceCollection services)
        {
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

            Configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();

            services.AddSingleton(Configuration);
            services.AddTransient<Functions, Functions>();
            services.AddLogging(builder => builder.AddConsole());
        }
    }
}

现在我得到了这个错误,它意味着function类中的容器没有被解析:

代码语言:javascript
运行
复制
fail: Host.Results[0]

System.InvalidOperationException:尝试激活'Gateway.WebJob.Functions‘时,无法解析类型为'SimpleInjector.Container’的服务。在Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp,类型类型,类型requiredBy,布尔值isDefaultParameterRequired)在lambda_method(闭包,IServiceProvider,在C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 37的Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstanceT中的Object[] )在Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.的C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 44中的Object[] functionInstance)Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance的C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 846中的ParameterHelper.Initialize(),C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 117中的CancellationToken cancellationToken)

EN

回答 1

Stack Overflow用户

发布于 2019-12-01 23:38:29

我自己刚刚尝试过,但只要在简单注入器集成中启用了“自动交叉连接”(这是默认设置),您就应该能够在无需执行任何操作的情况下注入IHubContext<T>实现。

下面是一个启动类的示例:

代码语言:javascript
运行
复制
public class Startup
{
    private readonly Container container = new Container();
    public Startup(IConfiguration configuration) => Configuration = configuration;
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        // default asp stuff here

        // add signalr
        services.AddSignalR();

        // add simple injector (enables auto cross wiring)
        services.AddSimpleInjector(this.container, options =>
        {
            options.AddAspNetCore().AddControllerActivation();
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseSimpleInjector(container);

        app.UseCookiePolicy();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

这是一个注入到控制器中的集线器上下文,它是由Simple Injector创建的:

代码语言:javascript
运行
复制
public class HomeController : Controller
{
    private readonly IHubContext<MyHub> context;

    public HomeController(IHubContext<MyHub> context, Container container)
    {
        this.context = context;
    }

    public IActionResult Index()
    {
        return View();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59111467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档