protected override void OnMessageReceived(IWebSocketContext context, byte[] buffer, IWebSocketReceiveResult result) { //TODO: Considering to send data from client side as binary Streamed JSON for performance in the future ! //Value type reference as byte[] and/or string are not good for performance string methodProxyJson = buffer.ToText(); Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { MethodProxy taksInput = null; MethodProxy taksOutput = null; try { taksInput = ContextBridge.GetMethodProxyFromJSON(methodProxyJson); taksOutput = ContextBridge.Receive(taksInput); } catch (Exception ex) { Console.WriteLine("Error: [Native] - BlazorContextBridge.Receive: " + ex.Message); } try { string jsonReturnValue = ContextBridge.GetJSONReturnValue(taksOutput); SendMessageToClient(jsonReturnValue); } catch (Exception ex) { Console.WriteLine("Error: [Native] - BlazorContextBridge.Send: " + ex.Message); } }); }
private static bool MethodProxyReceiver(string methodProxyJson, bool socketSuccess) { MethodProxy resultProxy = null; try { resultProxy = BridgeSerializer.Deserialize <MethodProxy>(ref methodProxyJson); } catch (Exception ex) { //Actually if we have an exception here that can mean that the user data has seem class not deserializable //between native and Blazor side. As we are probably in a waiting Task scenario, we must try to forward //the exception to the waiting task by fetching it's TaskId. //It will be easier to debug then if (TryGetDefaultFallbackMethodProxy(methodProxyJson, ex, out MethodProxy defaultProxy)) { return(BlazorCommonDispatcher.Receive(defaultProxy, socketSuccess)); } //Otherwise returning false. The task may be blocked in a waiting state forever //TODO: We should implement some kind of CancellationToken in the future on interop method signatures //forcing the business code to continue return(false); } return(BlazorCommonDispatcher.Receive(resultProxy, socketSuccess)); }
public static void Connect(int Port = -1) { if (Port <= 0) { Port = DEF_PORT; } try { RpcInvokeProxy = new RpcInvokeProxy(Port); ServerProxy = MethodProxy.CreateProxy <IService>(RpcInvokeProxy); } catch { if (Port != DEF_PORT) { try { RpcInvokeProxy = new RpcInvokeProxy(DEF_PORT); ServerProxy = MethodProxy.CreateProxy <IService>(RpcInvokeProxy); } catch { ConnectFail(DEF_PORT); } } else { ConnectFail(Port); } } }
public MethodProxyTest() { object decorated = DispatchProxy.Create <IFoo, MethodProxy <IFoo> >(); _proxy = ((MethodProxy <IFoo>)decorated); _proxiedDecorator = (IFoo)_proxy; }
public static bool Receive(string methodProxyJson) { if (string.IsNullOrEmpty(methodProxyJson)) { return(false); } InternalHelper.SetTimeout(() => { MethodProxy resultProxy = BridgeSerializer.Deserialize <MethodProxy>(methodProxyJson); var taskToReturn = MethodDispatcher.GetTaskDispatcher(resultProxy.TaskIdentity); MethodDispatcher.SetTaskResult(resultProxy.TaskIdentity, resultProxy); if (taskToReturn == null) { return; } taskToReturn.RunSynchronously(); MethodDispatcher.ClearTask(resultProxy.TaskIdentity); }, 10); return(true); }
public static async Task <MethodProxy> Receive(MethodProxy methodProxy) { object defaultValue = default(object); try { Type iface = methodProxy.InterfaceType.ResolvedType(); object concreteService = DependencyServiceExtension.Get(iface); MethodInfo baseMethod = MethodProxyHelper.GetClassMethodInfo(concreteService.GetType(), iface, methodProxy.MethodIndex); //In case of failure, getting Default Return Type defaultValue = GetDefault(baseMethod.ReturnType); DispatchInvokation(methodProxy, baseMethod, concreteService); if (methodProxy.AsyncTask) { await((Task)methodProxy.ReturnValue); } methodProxy.ReturnValue = GetResultFromTask(methodProxy.ReturnType.ResolvedType(), (Task)methodProxy.ReturnValue); } catch (Exception ex) { ConsoleHelper.WriteError($"[Native] - {(ex.InnerException != null ? ex.InnerException.Message : ex.Message)}"); methodProxy.ExceptionDescriptor = new ExceptionDescriptor(ex.InnerException != null ? ex.InnerException : ex); methodProxy.ReturnValue = defaultValue; methodProxy.TaskSuccess = false; } return(methodProxy); }
/// <summary> /// Manage In and Out call of Method /// </summary> /// <param name="webview"></param> /// <param name="json"></param> public static void BridgeEvaluator(BlazorWebView webview, MethodProxy taskInput, Action <string> outEvaluator = null) { //We must evaluate data on main thread, as some platform doesn't //support to be executed from a non-UI thread for UI //or Webview bridge Device.BeginInvokeOnMainThread(delegate() { MethodProxy returnValue = Receive(taskInput); string jsonReturnValue = GetJSONReturnValue(returnValue); //TODO: Manage missed returns value if the websocket disconnect, or discard them ? WebApplicationFactory.GetBlazorContextBridgeServer().SendMessageToClient(jsonReturnValue); //var receiveEvaluator = webview.GetReceiveEvaluator(jsonReturnValue); //if (outEvaluator != null) //{ // outEvaluator(receiveEvaluator); //} //else //{ // webview.Eval(receiveEvaluator); //} }); }
public void SendMessage(string methodProxyJson) { //TODO: Considering to send data from client side as binary Streamed JSON for performance in the future ! //TODO: Still, the mismatching CLR type namespace need to be fixed first //Value type reference as byte[] and/or string are not good for performance Xamarin.Forms.Device.BeginInvokeOnMainThread(async() => { MethodProxy taksInput = null; MethodProxy taksOutput = null; try { taksInput = ContextBridge.GetMethodProxyFromJSON(ref methodProxyJson); taksOutput = await ContextBridge.Receive(taksInput); } catch (Exception ex) { ConsoleHelper.WriteLine("Error: [Native] - BlazorContextBridge.Receive: " + ex.Message); } try { string jsonReturnValue = ContextBridge.GetJSONReturnValue(taksOutput); SendMessageToClient(jsonReturnValue); } catch (Exception ex) { ConsoleHelper.WriteLine("Error: [Native] - BlazorContextBridge.Send: " + ex.Message); } }); }
internal static Task Send(MethodProxy methodProxy) { string csharpProxy = BridgeSerializer.Serialize(methodProxy); BlazorMobileComponent.GetJSRuntime().InvokeAsync <bool>("contextBridgeSend", csharpProxy); return(Task.CompletedTask); }
private static bool TryGetDefaultFallbackMethodProxy(string methodProxyJson, Exception forwardedException, out MethodProxy defaultProxy) { defaultProxy = null; try { //We will only fetch required data for defaulting JObject methodProxyObject = JObject.Parse(methodProxyJson); if (!methodProxyObject.TryGetValue(nameof(MethodProxy.TaskIdentity), out JToken TaskIdentityToken)) { return(false); } Guid TaskIdentity = Guid.Parse(TaskIdentityToken.Value <string>()); defaultProxy = new MethodProxy() { TaskIdentity = TaskIdentity, TaskSuccess = false, ExceptionDescriptor = new ExceptionDescriptor($"An error occured during data deserialization on Blazor side while receiving data from native side. Check that your used types are serializable and present on both Blazor & native side. See InnerException for more details.") { InnerException = forwardedException } }; return(true); } catch (Exception) { return(false); } }
internal static void SetTaskResult(Guid taskIdentity, MethodProxy resultProxy) { if (!_taskDispatcher.ContainsKey(taskIdentity)) { return; } _taskDispatcher[taskIdentity].ResultData = resultProxy; }
static Controller() { Instance = new Controller(); Port = NetHelper.GetAvailablePort(DEF_PORT); RpcInvokeProxy = new RpcInvokeProxy(Port); ClientProxy = MethodProxy.CreateProxy <IClient>(RpcInvokeProxy); Log.Info($"Listen port {Port}"); }
public InvokeMethodProxy() { //OkToRun = true; TestName = "Invoking a method using a MethodProxy"; var mi = GetType().GetMethod("SomeOperation"); m_proxy = new MethodProxy(mi); }
public InvokeMethodInvoker() { //OkToRun = true; TestName = "Invoking a method using a MethodProxy' Invoker directly"; var mi = GetType().GetMethod("SomeOperation"); m_invoker = MethodProxy.CreateInvoker(mi); }
internal static Task <TReturnType> CreateTaskDispatcher <TReturnType>(MethodProxy methodProxy) { Guid taskId = Guid.Empty; var task = CreateTaskDispatcher <TReturnType>(out taskId); methodProxy.TaskIdentity = taskId; return(task); }
public static async Task Send(MethodProxy methodProxy) { string csharpProxy = BridgeSerializer.Serialize(methodProxy); InternalHelper.SetTimeout(async() => { await JSRuntime.Current.InvokeAsync <bool>("contextBridgeSend", csharpProxy); }, 100); }
/// <summary> /// This shorthand is only called from ElectronNET implementation / runtime. /// The main reason is that BlazorMobile.Web does not have a direct to the native side Receive method even if in ElectronNET implementation /// they are in the same memory space. This shorthand is used as a Bridge to this method, as *BlazorMobile.ElectronNET has access to both assemblies. /// </summary> /// <param name="methodProxy"></param> /// <returns></returns> public static Task <MethodProxy> CallNativeReceive(MethodProxy methodProxy) { if (_nativeReceiveMethod == null) { throw new InvalidOperationException("ERROR: Native receive delegate has not been set in BlazorMobile.Common"); } return(_nativeReceiveMethod(methodProxy)); }
public object Main(Dictionary <string, object> args) { if (lake == null) { throw new System.InvalidOperationException("Lake has not been inject!"); } var methodProxy = new MethodProxy(this, this.FindEntryPoint(), lake + GetSepLake(args)); return(methodProxy.Invoke(args ?? new Dictionary <string, object>())); }
public void CustomArgsTest() { MethodProxy maxProxy = new MethodProxy(this, nameof(Max), LakeExtension.Empty); var args = new Dictionary <string, object>() { { "x", 1 }, { "y", 2 } }; int result = (int)maxProxy.Invoke(args); Assert.IsTrue(result == 2); }
//1.代理模式用于提供的服务的对象不在本台计算机上, //使用实际对象的时候需要复杂的通讯,代理可以封装通讯的过程。 //2.代理模式还可以使用在不停的切换需要使用的对象时(如下例所示) static void Main(string[] args) { Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Namespace); MethodProxy proxy = new MethodProxy(); proxy.Method = new Method(); Console.WriteLine("1 + 2 = " + proxy.Add(1, 2) + " is right."); proxy.Method = new MethodWrong(); Console.WriteLine("1 + 2 = " + proxy.Add(1, 2) + " is wrong."); Console.ReadKey(); }
public static void ClearRequestValues(MethodProxy methodResult) { if (methodResult == null) { return; } methodResult.GenericTypes = null; methodResult.InterfaceType = null; methodResult.Parameters = null; }
public void TestMethodProxy_NoParams() { var d = new Data { fieldObject = "Hi" }; var mi = typeof(Data).GetMethod("GetFieldObject"); var proxy = new MethodProxy(mi); var s = proxy.Invoke(d, new object[0]); Assert.AreEqual("Hi", s, "Bad Conversion"); }
public static bool Receive(string methodProxyJson, bool socketSuccess) { if (string.IsNullOrEmpty(methodProxyJson)) { return(false); } InternalHelper.SetTimeout(() => { MethodProxy resultProxy = BridgeSerializer.Deserialize <MethodProxy>(ref methodProxyJson); var taskToReturn = MethodDispatcher.GetTaskDispatcher(resultProxy.TaskIdentity); if (taskToReturn == null) { return; } if (socketSuccess && resultProxy.TaskSuccess) { MethodDispatcher.SetTaskResult(resultProxy.TaskIdentity, resultProxy); } else { Exception exception = null; //If success value (from javascript) is false, like unable to connect to websocket //or if the native task failed with an exception, cancel the current task, that will throw if (!socketSuccess) { exception = new InvalidOperationException($"BlazorMobile was unable to connect to native through websocket server to execute task {resultProxy.TaskIdentity}"); } else if (resultProxy.ExceptionDescriptor != null) { //We have some message to send in this case exception = new Exception(resultProxy.ExceptionDescriptor.Message); } else { //Sending uncustomized message exception = new InvalidOperationException($"Task {resultProxy.TaskIdentity} has thrown an exception on native side. See log for more info."); } MethodDispatcher.SetTaskAsFaulted(resultProxy.TaskIdentity, exception); } taskToReturn.RunSynchronously(); //Clear task from task list. Should then call the task to execute. It will throw if it has been cancelled MethodDispatcher.ClearTask(resultProxy.TaskIdentity); }, 10); return(true); }
public void TestMethodProxy_VoidFn() { var d = new Data(); var mi = typeof(Data).GetMethod("InitFieldPrimitive"); var proxy = new MethodProxy(mi); Assert.AreEqual(0, d.fieldPrimitive, "Should be default value"); var s = proxy.Invoke(d, new object[0]); Assert.IsNull(s, "retval should be null"); Assert.AreEqual(69, d.fieldPrimitive, "Should have been set"); }
public object?Main(Dictionary <string, object> args) { if (lake == null) { throw new InvalidOperationException("Lake has not been inject!"); } var methodProxy = new MethodProxy(this, this.FindEntryPoint(), lake + GetSepLake(args)); try { return(methodProxy.Invoke(args ?? new Dictionary <string, object>())); } catch (TargetInvocationException e) when(e.InnerException?.GetType() == typeof(LeafUIExtension.LeafExtensionTerminatedException)) { return(default);
public static IInterceptTest GetProxy() { InterceptTestClass testClass = new InterceptTestClass(); IInterceptTest interceptTest = MethodProxy.Intercept <IInterceptTest>(testClass, (sender, arg) => { Log.Info(arg); } , (sender, arg) => { Log.Info(arg); }); return(interceptTest); }
public void TestMethodProxy_BoolParam() { var d = new Data { fieldPrimitive = 42, propertyPrimitive = 3.14 }; var mi = typeof(Data).GetMethod("GetPrimitiveValue"); var proxy = new MethodProxy(mi); var s = proxy.Invoke(d, new object[] { true }); Assert.AreEqual("42", s, "Bad Conversion"); s = proxy.Invoke(d, new object[] { false }); Assert.AreEqual("3.14", s, "Bad Conversion"); }
private static void DispatchInvokation(MethodProxy methodProxy, MethodInfo baseMethod, object concreteService) { if (methodProxy.GenericTypes != null && methodProxy.GenericTypes.Length > 0) { Type[] genericTypes = methodProxy.GenericTypes.Select(p => p.ResolvedType()).ToArray(); methodProxy.ReturnValue = baseMethod.MakeGenericMethod(genericTypes).Invoke(concreteService, methodProxy.Parameters); methodProxy.TaskSuccess = true; } else { methodProxy.ReturnValue = baseMethod.Invoke(concreteService, methodProxy.Parameters); methodProxy.TaskSuccess = true; } }
private void RunRoutines <T>() { Task.Run(() => { try { var instance = new ObjectBuilder(typeof(T), Lake).Build(); var mProxy = new MethodProxy(instance, ROUTINE_DO_METHOD_NAME, Lake); mProxy.Invoke(); } catch (Exception e) { SLogger <EssentialsLibrarin> .Warn("Routine is failed", e); } }); }
public object?Main(Dictionary <string, object> args) { if (lake == null) { throw new InvalidOperationException("Lake has not been inject!"); } var methodProxy = new MethodProxy(this, this.FindEntryPoint(), lake + GetSepLake(args)); try { return(methodProxy.Invoke(args ?? new Dictionary <string, object>())); } catch (TargetInvocationException e) { throw e.InnerException; } }