private Task <InteropHandshakeResult> AttachInteropAsync() { var resultTcs = new TaskCompletionSource <InteropHandshakeResult>(); // These hacks can go away once there's a proper IPC channel for event notifications etc. var selfAsDotNetObjectReference = typeof(DotNetObjectReference).GetMethod(nameof(DotNetObjectReference.Create)) .MakeGenericMethod(GetType()) .Invoke(null, new[] { this }); var selfAsDotnetObjectReferenceId = (long)typeof(JSRuntime).GetMethod("TrackObjectReference", BindingFlags.NonPublic | BindingFlags.Instance) .MakeGenericMethod(GetType()) .Invoke(_jsRuntime, new[] { selfAsDotNetObjectReference }); _ipc.Once("components:init", args => { var argsArray = (object[])args; var initialUriAbsolute = ((JsonElement)argsArray[0]).GetString(); var baseUriAbsolute = ((JsonElement)argsArray[1]).GetString(); resultTcs.TrySetResult(new InteropHandshakeResult(baseUriAbsolute, initialUriAbsolute)); }); _ipc.On("BeginInvokeDotNetFromJS", args => { var argsArray = (object[])args; var assemblyName = argsArray[1] != null ? ((JsonElement)argsArray[1]).GetString() : null; var methodIdentifier = ((JsonElement)argsArray[2]).GetString(); var dotNetObjectId = ((JsonElement)argsArray[3]).GetInt64(); var callId = ((JsonElement)argsArray[0]).GetString(); var argsJson = ((JsonElement)argsArray[4]).GetString(); // As a temporary hack, intercept blazor.desktop.js's JS interop calls for event notifications, // and direct them to our own instance. This is to avoid needing a static BlazorHybridRenderer.Instance. // Similar temporary hack for navigation notifications // TODO: Change blazor.desktop.js to use a dedicated IPC call for these calls, not JS interop. if (assemblyName == "Microsoft.MobileBlazorBindings.WebView") { assemblyName = null; dotNetObjectId = selfAsDotnetObjectReferenceId; } DotNetDispatcher.BeginInvokeDotNet( _jsRuntime, new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId), argsJson); }); _ipc.On("EndInvokeJSFromDotNet", args => { var argsArray = (object[])args; DotNetDispatcher.EndInvokeJS( _jsRuntime, ((JsonElement)argsArray[2]).GetString()); }); _webView.Source = new XF.UrlWebViewSource { Url = $"{BlazorAppScheme}://0.0.0.0/" }; return(resultTcs.Task); }