public override CircuitHost CreateCircuitHost(HttpContext httpContext, IClientProxy client) { if (!StartupActions.TryGetValue(httpContext.Request.Path, out var config)) { var message = $"Could not find a Blazor startup action for request path {httpContext.Request.Path}"; throw new InvalidOperationException(message); } var scope = _scopeFactory.CreateScope(); var jsRuntime = new RemoteJSRuntime(client); var rendererRegistry = new RendererRegistry(); var renderer = new RemoteRenderer(scope.ServiceProvider, rendererRegistry, jsRuntime, client); var synchronizationContext = new CircuitSynchronizationContext(); var circuitHost = new CircuitHost( scope, client, rendererRegistry, renderer, config, jsRuntime, synchronizationContext); // Initialize per-circuit data that services need (circuitHost.Services.GetRequiredService <IJSRuntimeAccessor>() as DefaultJSRuntimeAccessor).JSRuntime = jsRuntime; (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; return(circuitHost); }
public void Dispose_DisposesResources() { // Arrange var serviceScope = new Mock <IServiceScope>(); var clientProxy = Mock.Of <IClientProxy>(); var renderRegistry = new RendererRegistry(); var jsRuntime = Mock.Of <IJSRuntime>(); var syncContext = new CircuitSynchronizationContext(); var remoteRenderer = new TestRemoteRenderer( Mock.Of <IServiceProvider>(), renderRegistry, jsRuntime, clientProxy, syncContext); var circuitHost = new CircuitHost(serviceScope.Object, clientProxy, renderRegistry, remoteRenderer, configure: _ => { }, jsRuntime: jsRuntime, synchronizationContext: syncContext); // Act circuitHost.Dispose(); // Assert serviceScope.Verify(s => s.Dispose(), Times.Once()); Assert.True(remoteRenderer.Disposed); }
/// <summary> /// Sets the current <see cref="Circuits.Circuit"/>. /// </summary> /// <param name="circuitHost">The <see cref="Circuits.Circuit"/>.</param> /// <remarks> /// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store the circuit /// and other related values such as the <see cref="IJSRuntime"/> and <see cref="Renderer"/> /// in the local execution context. Application code should not need to call this method, /// it is primarily used by the Server-Side Components infrastructure. /// </remarks> public static void SetCurrentCircuitHost(CircuitHost circuitHost) { _current.Value = circuitHost ?? throw new ArgumentNullException(nameof(circuitHost)); Microsoft.JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime); RendererRegistry.SetCurrentRendererRegistry(circuitHost.RendererRegistry); }
public CircuitHost( IServiceScope scope, IClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, Action <IComponentsApplicationBuilder> configure, IJSRuntime jsRuntime, CircuitSynchronizationContext synchronizationContext, CircuitHandler[] circuitHandlers) { _scope = scope ?? throw new ArgumentNullException(nameof(scope)); Client = client ?? throw new ArgumentNullException(nameof(client)); RendererRegistry = rendererRegistry ?? throw new ArgumentNullException(nameof(rendererRegistry)); Renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); _configure = configure ?? throw new ArgumentNullException(nameof(configure)); JSRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime)); SynchronizationContext = synchronizationContext ?? throw new ArgumentNullException(nameof(synchronizationContext)); Services = scope.ServiceProvider; Circuit = new Circuit(this); _circuitHandlers = circuitHandlers; Renderer.UnhandledException += Renderer_UnhandledException; SynchronizationContext.UnhandledException += SynchronizationContext_UnhandledException; }
private static CircuitHost GetCircuitHost( IServiceScope serviceScope = null, RemoteRenderer remoteRenderer = null, CircuitHandler[] handlers = null) { serviceScope = serviceScope ?? Mock.Of <IServiceScope>(); var clientProxy = Mock.Of <IClientProxy>(); var renderRegistry = new RendererRegistry(); var jsRuntime = Mock.Of <IJSRuntime>(); var syncContext = new CircuitSynchronizationContext(); remoteRenderer = remoteRenderer ?? GetRemoteRenderer(); handlers = handlers ?? Array.Empty <CircuitHandler>(); return(new CircuitHost( serviceScope, clientProxy, renderRegistry, remoteRenderer, configure: _ => { }, jsRuntime: jsRuntime, synchronizationContext: syncContext, handlers)); }
public CircuitHost( string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IList <ComponentDescriptor> descriptors, IDispatcher dispatcher, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger) { CircuitId = circuitId; _scope = scope ?? throw new ArgumentNullException(nameof(scope)); Dispatcher = dispatcher; Client = client; RendererRegistry = rendererRegistry ?? throw new ArgumentNullException(nameof(rendererRegistry)); Descriptors = descriptors ?? throw new ArgumentNullException(nameof(descriptors)); Renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); JSRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime)); _logger = logger; Services = scope.ServiceProvider; Circuit = new Circuit(this); _circuitHandlers = circuitHandlers; Renderer.UnhandledException += Renderer_UnhandledException; Renderer.UnhandledSynchronizationException += SynchronizationContext_UnhandledException; }
public void RendererRegistry_Remove_DoesNothingOnNonWASM() { // Act var result = RendererRegistry.TryRemove(123); // Assert Assert.False(result); }
public void RendererRegistry_Find_ThrowsErrorOnNonWASM() { // Act Exception ex = Assert.Throws <ArgumentException>(() => RendererRegistry.Find(123)); // Assert Assert.Equal("There is no renderer with ID 123.", ex.Message); }
public override CircuitHost CreateCircuitHost( HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute) { var components = ResolveComponentMetadata(httpContext, client); var scope = _scopeFactory.CreateScope(); var encoder = scope.ServiceProvider.GetRequiredService <HtmlEncoder>(); var jsRuntime = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>(); var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>(); jsRuntime.Initialize(client); componentContext.Initialize(client); var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService <IUriHelper>(); if (client != CircuitClientProxy.OfflineClient) { uriHelper.Initialize(uriAbsolute, baseUriAbsolute, jsRuntime); } else { uriHelper.Initialize(uriAbsolute, baseUriAbsolute); } var rendererRegistry = new RendererRegistry(); var dispatcher = Renderer.CreateDefaultDispatcher(); var renderer = new RemoteRenderer( scope.ServiceProvider, rendererRegistry, jsRuntime, client, dispatcher, encoder, _loggerFactory.CreateLogger <RemoteRenderer>()); var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>() .OrderBy(h => h.Order) .ToArray(); var circuitHost = new CircuitHost( scope, client, rendererRegistry, renderer, components, dispatcher, jsRuntime, circuitHandlers, _loggerFactory.CreateLogger <CircuitHost>()); // Initialize per - circuit data that services need (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; return(circuitHost); }
public WebAssemblyRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, JSComponentInterop jsComponentInterop) : base(serviceProvider, loggerFactory, DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(), jsComponentInterop) { // The WebAssembly renderer registers and unregisters itself with the static registry RendererId = RendererRegistry.Add(this); _logger = loggerFactory.CreateLogger <WebAssemblyRenderer>(); ElementReferenceContext = DefaultWebAssemblyJSRuntime.Instance.ElementReferenceContext; }
/// <summary> /// Sets the current <see cref="Circuits.Circuit"/>. /// </summary> /// <param name="circuitHost">The <see cref="Circuits.Circuit"/>.</param> /// <remarks> /// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store related values such as the /// <see cref="IJSRuntime"/> and <see cref="Renderer"/> /// in the local execution context. Application code should not need to call this method, /// it is primarily used by the Server-Side Components infrastructure. /// </remarks> public static void SetCurrentCircuitHost(CircuitHost circuitHost) { if (circuitHost is null) { throw new ArgumentNullException(nameof(circuitHost)); } JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime); RendererRegistry.SetCurrentRendererRegistry(circuitHost.RendererRegistry); }
public static Task DispatchEvent(WebEventDescriptor eventDescriptor, string eventArgsJson) { var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); var webEvent = WebEventData.Parse(renderer, eventDescriptor, eventArgsJson); return(renderer.DispatchEventAsync( webEvent.EventHandlerId, webEvent.EventFieldInfo, webEvent.EventArgs)); }
public static Task DispatchEvent(WebEventDescriptor eventDescriptor, string eventArgsJson) { var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); var jsonSerializerOptions = DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(); var webEvent = WebEventData.Parse(renderer, jsonSerializerOptions, eventDescriptor, eventArgsJson); return(renderer.DispatchEventAsync( webEvent.EventHandlerId, webEvent.EventFieldInfo, webEvent.EventArgs)); }
/// <summary> /// Creates a new <see cref="RemoteRenderer"/>. /// </summary> /// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param> /// <param name="rendererRegistry">The <see cref="RendererRegistry"/>.</param> /// <param name="jsRuntime">The <see cref="IJSRuntime"/>.</param> /// <param name="client">The <see cref="IClientProxy"/>.</param> public RemoteRenderer( IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client) : base(serviceProvider) { _rendererRegistry = rendererRegistry; _jsRuntime = jsRuntime; _client = client; _id = _rendererRegistry.Add(this); }
public static Item Create(ItemData data) { var item = new Item { UseTime = data.UseTime, Id = data.Id, Type = data.Type, AutoPickup = data.AutoPickup, Animation = data.Animation, Automatic = data.Automatic, SingleUse = data.SingleUse, Scourged = data.Scourged, Uses = ParseUses(data.Uses) }; if (data.Renderer != JsonValue.Null) { if (data.Renderer.IsString) { var name = data.Renderer.AsString; item.Renderer = RendererRegistry.Create(name); CheckRendererForNull(item, name); } else if (data.Renderer.IsJsonObject) { var name = data.Renderer["id"].String("bk:Angled"); item.Renderer = RendererRegistry.Create(name); CheckRendererForNull(item, name); if (item.Renderer != null) { item.Renderer.Item = item; item.Renderer.Setup(data.Renderer); } } else { Log.Error($"Invalid renderer declaration in item {data.Id}"); } } foreach (var u in item.Uses) { u.Item = item; u.Init(); } return(item); }
/// <summary> /// Creates a new <see cref="RemoteRenderer"/>. /// </summary> /// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param> /// <param name="rendererRegistry">The <see cref="RendererRegistry"/>.</param> /// <param name="jsRuntime">The <see cref="IJSRuntime"/>.</param> /// <param name="client">The <see cref="IClientProxy"/>.</param> /// <param name="syncContext">A <see cref="SynchronizationContext"/> that can be used to serialize renderer operations.</param> public RemoteRenderer( IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client, SynchronizationContext syncContext) : base(serviceProvider) { _rendererRegistry = rendererRegistry; _jsRuntime = jsRuntime; _client = client; _syncContext = syncContext; _id = _rendererRegistry.Add(this); }
/// <summary> /// Creates a new <see cref="RemoteRenderer"/>. /// </summary> /// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param> /// <param name="rendererRegistry">The <see cref="RendererRegistry"/>.</param> /// <param name="jsRuntime">The <see cref="IJSRuntime"/>.</param> /// <param name="client">The <see cref="IClientProxy"/>.</param> /// <param name="syncContext">A <see cref="SynchronizationContext"/> that can be used to serialize renderer operations.</param> public RemoteRenderer( IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client, IDispatcher dispatcher, ILogger logger) : base(serviceProvider, dispatcher) { _rendererRegistry = rendererRegistry; _jsRuntime = jsRuntime; _client = client; _id = _rendererRegistry.Add(this); _logger = logger; }
public static async Task DispatchEvent(byte[] eventInfo) { var payload = GetJsonElements(eventInfo); var eventDescriptor = WebEventDescriptorReader.Read(payload.EventDescriptor); var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); var webEvent = WebEventData.Parse( renderer, DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(), eventDescriptor, payload.EventArgs); await renderer.DispatchEventAsync( webEvent.EventHandlerId, webEvent.EventFieldInfo, webEvent.EventArgs); }
/// <summary> /// Creates a new <see cref="RemoteRenderer"/>. /// </summary> public RemoteRenderer( IServiceProvider serviceProvider, ILoggerFactory loggerFactory, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, CircuitClientProxy client, HtmlEncoder encoder, ILogger logger) : base(serviceProvider, loggerFactory, encoder.Encode) { _rendererRegistry = rendererRegistry; _jsRuntime = jsRuntime; _client = client; Id = _rendererRegistry.Add(this); _logger = logger; }
public static Task DispatchEvent(WebEventDescriptor eventDescriptor, string eventArgsJson) { var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); // JsonSerializerOptions are tightly bound to the JsonContext. Cache it on first use using a copy // of the serializer settings. if (_jsonContext is null) { var jsonSerializerOptions = DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(); _jsonContext = new(new JsonSerializerOptions(jsonSerializerOptions)); } var webEvent = WebEventData.Parse(renderer, _jsonContext, eventDescriptor, eventArgsJson); return(renderer.DispatchEventAsync( webEvent.EventHandlerId, webEvent.EventFieldInfo, webEvent.EventArgs)); }
public static CircuitHost Create( string circuitId = null, IServiceScope serviceScope = null, RemoteRenderer remoteRenderer = null, CircuitHandler[] handlers = null, CircuitClientProxy clientProxy = null) { serviceScope = serviceScope ?? Mock.Of <IServiceScope>(); clientProxy = clientProxy ?? new CircuitClientProxy(Mock.Of <IClientProxy>(), Guid.NewGuid().ToString()); var renderRegistry = new RendererRegistry(); var jsRuntime = new RemoteJSRuntime(Options.Create(new CircuitOptions())); var dispatcher = Rendering.Renderer.CreateDefaultDispatcher(); if (remoteRenderer == null) { remoteRenderer = new RemoteRenderer( serviceScope.ServiceProvider ?? Mock.Of <IServiceProvider>(), NullLoggerFactory.Instance, new RendererRegistry(), jsRuntime, clientProxy, dispatcher, HtmlEncoder.Default, NullLogger.Instance); } handlers = handlers ?? Array.Empty <CircuitHandler>(); return(new TestCircuitHost( circuitId ?? Guid.NewGuid().ToString(), serviceScope, clientProxy, renderRegistry, remoteRenderer, new List <ComponentDescriptor>(), dispatcher, jsRuntime, handlers, NullLogger <CircuitHost> .Instance)); }
public override CircuitHost CreateCircuitHost(HttpContext httpContext, IClientProxy client) { if (!_options.StartupActions.TryGetValue(httpContext.Request.Path, out var config)) { var message = $"Could not find an ASP.NET Core Components startup action for request path '{httpContext.Request.Path}'."; throw new InvalidOperationException(message); } var scope = _scopeFactory.CreateScope(); var jsRuntime = new RemoteJSRuntime(client); var rendererRegistry = new RendererRegistry(); var dispatcher = Renderer.CreateDefaultDispatcher(); var renderer = new RemoteRenderer( scope.ServiceProvider, rendererRegistry, jsRuntime, client, dispatcher, _loggerFactory.CreateLogger <RemoteRenderer>()); var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>() .OrderBy(h => h.Order) .ToArray(); var circuitHost = new CircuitHost( scope, client, rendererRegistry, renderer, config, jsRuntime, circuitHandlers); // Initialize per-circuit data that services need (circuitHost.Services.GetRequiredService <IJSRuntimeAccessor>() as DefaultJSRuntimeAccessor).JSRuntime = jsRuntime; (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; return(circuitHost); }
private static CircuitHost GetCircuitHost( IServiceScope serviceScope = null, RemoteRenderer remoteRenderer = null, CircuitHandler[] handlers = null) { serviceScope = serviceScope ?? Mock.Of <IServiceScope>(); var clientProxy = Mock.Of <IClientProxy>(); var renderRegistry = new RendererRegistry(); var jsRuntime = Mock.Of <IJSRuntime>(); var dispatcher = Renderer.CreateDefaultDispatcher(); remoteRenderer = remoteRenderer ?? GetRemoteRenderer(dispatcher); handlers = handlers ?? Array.Empty <CircuitHandler>(); return(new CircuitHost( serviceScope, clientProxy, renderRegistry, remoteRenderer, new List <ComponentDescriptor>(), dispatcher, jsRuntime: jsRuntime, handlers)); }
private TestCircuitHost(string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IReadOnlyList <ComponentDescriptor> descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger) : base(circuitId, scope, client, rendererRegistry, renderer, descriptors, jsRuntime, circuitHandlers, logger) { }
public TestRemoteRenderer(IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client) : base(serviceProvider, NullLoggerFactory.Instance, rendererRegistry, jsRuntime, new CircuitClientProxy(client, "connection"), HtmlEncoder.Default, NullLogger.Instance) { }
public override CircuitHost CreateCircuitHost( HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute) { var components = ResolveComponentMetadata(httpContext, client); var scope = _scopeFactory.CreateScope(); var encoder = scope.ServiceProvider.GetRequiredService <HtmlEncoder>(); var jsRuntime = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>(); var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>(); jsRuntime.Initialize(client); componentContext.Initialize(client); // You can replace the AuthenticationStateProvider with a custom one, but in that case initialization is up to you var authenticationStateProvider = scope.ServiceProvider.GetService <AuthenticationStateProvider>(); (authenticationStateProvider as FixedAuthenticationStateProvider)?.Initialize(httpContext.User); var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService <IUriHelper>(); if (client.Connected) { uriHelper.AttachJsRuntime(jsRuntime); uriHelper.InitializeState( uriAbsolute, baseUriAbsolute); } else { uriHelper.InitializeState(uriAbsolute, baseUriAbsolute); } var rendererRegistry = new RendererRegistry(); var dispatcher = Renderer.CreateDefaultDispatcher(); var renderer = new RemoteRenderer( scope.ServiceProvider, rendererRegistry, jsRuntime, client, dispatcher, encoder, _loggerFactory.CreateLogger <RemoteRenderer>()); var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>() .OrderBy(h => h.Order) .ToArray(); var circuitHost = new CircuitHost( scope, client, rendererRegistry, renderer, components, dispatcher, jsRuntime, circuitHandlers, _loggerFactory.CreateLogger <CircuitHost>()); // Initialize per - circuit data that services need (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; return(circuitHost); }
public TestRemoteRenderer(IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client) : base(serviceProvider, rendererRegistry, jsRuntime, client, CreateDefaultDispatcher(), NullLogger.Instance) { }
/// <inheritdoc /> protected override void Dispose(bool disposing) { base.Dispose(disposing); RendererRegistry.TryRemove(RendererId); }
public override CircuitHost CreateCircuitHost( HttpContext httpContext, CircuitClientProxy client, string baseUri, string uri, ClaimsPrincipal user) { // We do as much intialization as possible eagerly in this method, which makes the error handling // story much simpler. If we throw from here, it's handled inside the initial hub method. var components = ResolveComponentMetadata(httpContext, client); var scope = _scopeFactory.CreateScope(); var encoder = scope.ServiceProvider.GetRequiredService <HtmlEncoder>(); var jsRuntime = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>(); var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>(); jsRuntime.Initialize(client); componentContext.Initialize(client); var authenticationStateProvider = scope.ServiceProvider.GetService <AuthenticationStateProvider>() as IHostEnvironmentAuthenticationStateProvider; if (authenticationStateProvider != null) { var authenticationState = new AuthenticationState(httpContext.User); // TODO: Get this from the hub connection context instead authenticationStateProvider.SetAuthenticationState(Task.FromResult(authenticationState)); } var navigationManager = (RemoteNavigationManager)scope.ServiceProvider.GetRequiredService <NavigationManager>(); var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService <INavigationInterception>(); if (client.Connected) { navigationManager.AttachJsRuntime(jsRuntime); navigationManager.Initialize(baseUri, uri); navigationInterception.AttachJSRuntime(jsRuntime); } else { navigationManager.Initialize(baseUri, uri); } var rendererRegistry = new RendererRegistry(); var renderer = new RemoteRenderer( scope.ServiceProvider, _loggerFactory, rendererRegistry, jsRuntime, client, encoder, _loggerFactory.CreateLogger <RemoteRenderer>()); var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>() .OrderBy(h => h.Order) .ToArray(); var circuitHost = new CircuitHost( _circuitIdFactory.CreateCircuitId(), scope, client, rendererRegistry, renderer, components, jsRuntime, circuitHandlers, _loggerFactory.CreateLogger <CircuitHost>()); Log.CreatedCircuit(_logger, circuitHost); // Initialize per - circuit data that services need (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; circuitHost.SetCircuitUser(user); return(circuitHost); }
public TestRemoteRenderer(IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IJSRuntime jsRuntime, IClientProxy client, SynchronizationContext syncContext) : base(serviceProvider, rendererRegistry, jsRuntime, client, syncContext) { }