예제 #1
0
        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");
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
 public DesktopRenderer(IServiceProvider serviceProvider, IPC ipc, ILoggerFactory loggerFactory)
     : base(serviceProvider, loggerFactory)
 {
     _ipc       = ipc ?? throw new ArgumentNullException(nameof(ipc));
     _jsRuntime = serviceProvider.GetRequiredService <IJSRuntime>();
 }
예제 #4
0
 public DesktopJSRuntime(IPC ipc)
 {
     _ipc = ipc ?? throw new ArgumentNullException(nameof(ipc));
 }