private static async Task PerformHandshakeAsync(IPC ipc) { // Do a two-way handshake with the browser, this ensures that the appropriate // interop handlers have been set up before control returns to the user. // // The handshake sequence looks like this: // // 1. dotnet starts listening for components:init // 2. dotnet sends components:init repeatedly // 3. JS starts listening for components:init // 4. JS sends a components:init once it has received one from dotnet - it's ready // 5. dotnet receives components:init - it's ready // // Because either side might take any amount of time to start listening, // step 3 can occur at any point prior to step 4. The whole process works // because steps 1, 2, 4, and 5 can only occur in that order var cts = new CancellationTokenSource(); var incomingHandshakeCancellationToken = cts.Token; ipc.Once("components:init", args => { var argsArray = (object[])args; InitialUriAbsolute = ((JsonElement)argsArray[0]).GetString(); BaseUriAbsolute = ((JsonElement)argsArray[1]).GetString(); cts.Cancel(); }); Log("Waiting for interop connection"); while (!incomingHandshakeCancellationToken.IsCancellationRequested) { ipc.Send("components:init"); try { await Task.Delay(100, incomingHandshakeCancellationToken); } catch (TaskCanceledException) { } } Log("Interop connected"); }
private static async Task RunAsync <TStartup>(IPC ipc, CancellationToken appLifetime) { DesktopJSRuntime = new DesktopJSRuntime(ipc); await PerformHandshakeAsync(ipc); AttachJsInterop(ipc, appLifetime); var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(configure => configure.AddConsole()); serviceCollection.AddSingleton <NavigationManager>(DesktopNavigationManager.Instance); serviceCollection.AddSingleton <IJSRuntime>(DesktopJSRuntime); serviceCollection.AddSingleton <INavigationInterception, DesktopNavigationInterception>(); var startup = new ConventionBasedStartup(Activator.CreateInstance(typeof(TStartup))); startup.ConfigureServices(serviceCollection); var services = serviceCollection.BuildServiceProvider(); var builder = new DesktopApplicationBuilder(services); startup.Configure(builder, services); var loggerFactory = services.GetRequiredService <ILoggerFactory>(); DesktopRenderer = new DesktopRenderer(services, ipc, loggerFactory); DesktopRenderer.UnhandledException += (sender, exception) => { Console.Error.WriteLine(exception); }; foreach (var rootComponent in builder.Entries) { _ = DesktopRenderer.AddComponentAsync(rootComponent.componentType, rootComponent.domElementSelector); } }
public DesktopRenderer(IServiceProvider serviceProvider, IPC ipc, ILoggerFactory loggerFactory) : base(serviceProvider, loggerFactory) { _ipc = ipc ?? throw new ArgumentNullException(nameof(ipc)); _jsRuntime = serviceProvider.GetRequiredService <IJSRuntime>(); }
public DesktopJSRuntime(IPC ipc) { _ipc = ipc ?? throw new ArgumentNullException(nameof(ipc)); }