示例#1
0
        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));
        }
示例#3
0
 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;
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        /// <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);
            }
        }
示例#11
0
 internal static void SetTaskResult(Guid taskIdentity, MethodProxy resultProxy)
 {
     if (!_taskDispatcher.ContainsKey(taskIdentity))
     {
         return;
     }
     _taskDispatcher[taskIdentity].ResultData = resultProxy;
 }
示例#12
0
 static Controller()
 {
     Instance       = new Controller();
     Port           = NetHelper.GetAvailablePort(DEF_PORT);
     RpcInvokeProxy = new RpcInvokeProxy(Port);
     ClientProxy    = MethodProxy.CreateProxy <IClient>(RpcInvokeProxy);
     Log.Info($"Listen port {Port}");
 }
示例#13
0
        public InvokeMethodProxy()
        {
            //OkToRun = true;
            TestName = "Invoking a method using a MethodProxy";

            var mi = GetType().GetMethod("SomeOperation");

            m_proxy = new MethodProxy(mi);
        }
示例#14
0
        public InvokeMethodInvoker()
        {
            //OkToRun = true;
            TestName = "Invoking a method using a MethodProxy' Invoker directly";

            var mi = GetType().GetMethod("SomeOperation");

            m_invoker = MethodProxy.CreateInvoker(mi);
        }
示例#15
0
        internal static Task <TReturnType> CreateTaskDispatcher <TReturnType>(MethodProxy methodProxy)
        {
            Guid taskId = Guid.Empty;
            var  task   = CreateTaskDispatcher <TReturnType>(out taskId);

            methodProxy.TaskIdentity = taskId;

            return(task);
        }
示例#16
0
        public static async Task Send(MethodProxy methodProxy)
        {
            string csharpProxy = BridgeSerializer.Serialize(methodProxy);

            InternalHelper.SetTimeout(async() =>
            {
                await JSRuntime.Current.InvokeAsync <bool>("contextBridgeSend", csharpProxy);
            }, 100);
        }
示例#17
0
        /// <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));
        }
示例#18
0
        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>()));
        }
示例#19
0
        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);
        }
示例#20
0
        //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();
        }
示例#21
0
        public static void ClearRequestValues(MethodProxy methodResult)
        {
            if (methodResult == null)
            {
                return;
            }

            methodResult.GenericTypes  = null;
            methodResult.InterfaceType = null;
            methodResult.Parameters    = null;
        }
示例#22
0
        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);
        }
示例#24
0
        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");
        }
示例#25
0
        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);
示例#26
0
        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);
        }
示例#27
0
        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");
        }
示例#28
0
        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;
            }
        }
示例#29
0
 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);
         }
     });
 }
示例#30
0
        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;
            }
        }