예제 #1
0
        /// <summary>
        ///     Sends a message to the Javascript side and waits for the response
        /// </summary>
        /// <param name="messageString">Message identification, or string.Empty to send to all subscribers</param>
        /// <param name="argument">The argument to be send to the message subscriber</param>
        /// <typeparam name="TResult">The type of the expected result</typeparam>
        /// <typeparam name="TArgument">The type of the argument to send</typeparam>
        /// <returns>Returns the response of the last subscriber</returns>
        public virtual TResult Send <TResult, TArgument>(string messageString, TArgument argument)
        {
            var returnValue = HybridMessagingProxy.HandlerNewMessage(messageString, argument);

            try
            {
                return(ClassBridge.NormalizeVariable <TResult>(returnValue));
            }
            catch (Exception)
            {
                return(default(TResult));
            }
        }
예제 #2
0
 /// <summary>
 ///     Creates a new instance of this class
 /// </summary>
 /// <exception cref="InvalidGenericTypeException">Indicates that the passed generic type is not a valid class</exception>
 public ClassBridge()
 {
     if (!GenericType.IsClass)
     {
         throw new InvalidGenericTypeException();
     }
     lock (Lock)
     {
         if (Methods == null)
         {
             Methods = GenericType.GetMethods()
                       .Where(
                 info =>
                 info.IsPublic && !info.IsGenericMethod)
                       .ToDictionary(info => info, info => info.GetParameters());
         }
         if (Constructors == null)
         {
             Constructors = GenericType.GetConstructors()
                            .Where(
                 info =>
                 info.IsPublic && !info.IsGenericMethod)
                            .ToDictionary(info => info, info => info.GetParameters());
         }
         if (Properties == null)
         {
             Properties =
                 GenericType.GetProperties()
                 .Where(
                     info =>
                     Methods.ContainsKey(info.GetGetMethod()) ||
                     Methods.ContainsKey(info.GetSetMethod()))
                 .ToList();
         }
         if (Fields == null)
         {
             Fields = GenericType.GetFields().Where(info => info.IsPublic).ToList();
         }
         if (Events == null)
         {
             Events =
                 GenericType.GetEvents()
                 .Where(
                     info =>
                     Methods.ContainsKey(info.GetAddMethod()) &&
                     Methods.ContainsKey(info.GetRemoveMethod()))
                 .ToList();
         }
         foreach (
             var info in
             Events.Where(info => info.GetAddMethod().IsStatic || info.GetRemoveMethod().IsStatic))
         {
             var eventInvokerReturn = info.EventHandlerType.GetMethod("Invoke").ReturnType;
             if ((eventInvokerReturn == typeof(void)) || (eventInvokerReturn == typeof(object)))
             {
                 var del = ClassBridge.CreateProxyDelegateForEvent(info, null, RaiseEvent);
                 StaticEventsDelegates.Add(info, del);
                 info.AddEventHandler(null, del);
             }
             else
             {
                 var del = ClassBridge.CreateProxyDelegateForEvent(info, null,
                                                                   (instance, eventName, isVoid, eventArgs) =>
                                                                   ClassBridge.NormalizeVariable(RaiseEvent(instance, eventName, isVoid, eventArgs),
                                                                                                 eventInvokerReturn, false));
                 StaticEventsDelegates.Add(info, del);
                 info.AddEventHandler(null, del);
             }
         }
         if (SubEnumerations == null)
         {
             SubEnumerations =
                 GenericType.GetNestedTypes(BindingFlags.Public)
                 .Where(type => type.IsEnum)
                 .Select(EnumBridge.FromType)
                 .ToList();
             foreach (var subEnum in SubEnumerations)
             {
                 subEnum.PushJavascript += (sender, args) => OnPushJavascript(args);
             }
         }
         if (SubClasses == null)
         {
             SubClasses =
                 GenericType.GetNestedTypes(BindingFlags.Public)
                 .Where(type => type.IsClass && !typeof(Delegate).IsAssignableFrom(type))
                 .Select(ClassBridge.FromType)
                 .ToList();
             foreach (var subClasses in SubClasses)
             {
                 subClasses.PushJavascript += (sender, args) => OnPushJavascript(args);
             }
         }
     }
 }
예제 #3
0
 /// <summary>
 ///     Registers an instance of the generic type and adds it to the list of registered instances
 /// </summary>
 /// <param name="instance">The instance of the generic type to ad</param>
 /// <param name="variableName">The name of the variable that is accessible from the Javascript side</param>
 /// <returns>Returns <see langword="this" /> instance to be used for other operations</returns>
 public virtual ClassBridge <T> AddInstance(T instance, string variableName)
 {
     if (instance != null)
     {
         if (!Instances.ContainsKey(instance))
         {
             Instances.Add(instance, new List <string>());
             if (!InstancesEventsDelegates.ContainsKey(instance))
             {
                 InstancesEventsDelegates.Add(instance, new Dictionary <EventInfo, Delegate>());
             }
             foreach (
                 var info in
                 Events.Where(info => !info.GetAddMethod().IsStatic&& !info.GetRemoveMethod().IsStatic))
             {
                 var eventDelegate =
                     InstancesEventsDelegates[instance].FirstOrDefault(pair => pair.Key == info).Value;
                 if (eventDelegate == null)
                 {
                     var eventInvokerReturn = info.EventHandlerType.GetMethod("Invoke").ReturnType;
                     if ((eventInvokerReturn == typeof(void)) || (eventInvokerReturn == typeof(object)))
                     {
                         eventDelegate = ClassBridge.CreateProxyDelegateForEvent(info, instance, RaiseEvent);
                     }
                     else
                     {
                         eventDelegate = ClassBridge.CreateProxyDelegateForEvent(info, instance,
                                                                                 (o, s, arg3, arg4) =>
                                                                                 ClassBridge.NormalizeVariable(RaiseEvent(o, s, arg3, arg4), eventInvokerReturn,
                                                                                                               false));
                     }
                     InstancesEventsDelegates[instance].Add(info, eventDelegate);
                 }
                 info.AddEventHandler(instance, eventDelegate);
             }
             OnPushJavascript(
                 new FireJavascriptEventArgs(ClassBridge.GenerateInstanceChange(Identification,
                                                                                GlobalPool.GetInstanceId(instance), false)));
         }
     }
     if (!string.IsNullOrWhiteSpace(variableName))
     {
         foreach (
             var key in
             Instances.Keys.Where(key => key != instance)
             .Where(key => Instances[key].Contains(variableName))
             .ToArray())
         {
             RemoveInstance(variableName, key as T);
         }
         if (instance != null)
         {
             if (!Instances[instance].Contains(variableName))
             {
                 Instances[instance].Add(variableName);
                 OnPushJavascript(
                     new FireJavascriptEventArgs(ClassBridge.GenerateInstanceVariable(Identification,
                                                                                      GlobalPool.GetInstanceId(instance), variableName)));
             }
         }
         else
         {
             OnPushJavascript(
                 new FireJavascriptEventArgs(ClassBridge.GenerateInstanceVariable(Identification, null,
                                                                                  variableName)));
         }
     }
     return(this);
 }
예제 #4
0
        /// <summary>
        ///     Handles the passed request and returns the result
        /// </summary>
        /// <param name="method">The method name to handle</param>
        /// <param name="parameters">The method parameters</param>
        /// <param name="hasResult">A boolean value indicting if the handling process resulted in a value</param>
        /// <returns>Returns the value that created from the handling of the request</returns>
        public virtual object InterceptRequest(string method, Dictionary <string, object> parameters, out bool hasResult)
        {
            hasResult = false;
            MethodInfo      methodInfo       = null;
            ConstructorInfo constructorInfo  = null;
            var             methodParameters = new object[0];
            FieldInfo       fieldInfo        = null;
            object          fieldValue       = null;
            object          classInstance    = null;
            var             methodParts      = method.Split('/');

            if (methodParts.Length > 1)
            {
                method        = string.Join("/", methodParts, 1, methodParts.Length - 1);
                classInstance =
                    Instances.FirstOrDefault(
                        instance => GlobalPool.GetInstanceId(instance.Key) == methodParts[0]).Key;
            }
            lock (Lock)
            {
                if (string.IsNullOrWhiteSpace(method))
                {
                    if ((Constructors != null) && parameters.ContainsKey("arguments"))
                    {
                        var constructorParameters = parameters["arguments"] as JArray;
                        foreach (var pair in Constructors)
                        {
                            var matchedArguments = 0;
                            try
                            {
                                var param = new List <object>();
                                for (var i = 0; i < pair.Value.Length; i++)
                                {
                                    if ((constructorParameters != null) && (i < constructorParameters.Count))
                                    {
                                        param.Add(ClassBridge.NormalizeVariable(constructorParameters.ToArray()[i],
                                                                                pair.Value[i].ParameterType, true));
                                        matchedArguments++;
                                    }
                                    else
                                    {
                                        if (pair.Value[i].IsOptional)
                                        {
                                            param.Add(pair.Value[i].DefaultValue);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                                if ((param.Count != pair.Value.Length) ||
                                    (matchedArguments != (constructorParameters?.Count ?? 0)))
                                {
                                    continue;
                                }
                                methodParameters = param.ToArray();
                            }
                            catch (InvalidCastException)
                            {
                                // ignore
                            }
                            constructorInfo = pair.Key;
                        }
                    }
                }
                else
                {
                    if (Methods != null)
                    {
                        foreach (var pair in Methods.Where(pair => pair.Key.Name.Equals(method)))
                        {
                            var matchedArguments = 0;
                            try
                            {
                                var param = new List <object>();
                                for (var i = 0; i < pair.Value.Length; i++)
                                {
                                    if (i < parameters.Count)
                                    {
                                        if (pair.Value[i].Name == parameters.Keys.ToArray()[i])
                                        {
                                            param.Add(ClassBridge.NormalizeVariable(parameters.Values.ToArray()[i],
                                                                                    pair.Value[i].ParameterType, true));
                                            matchedArguments++;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        if (pair.Value[i].IsOptional)
                                        {
                                            param.Add(pair.Value[i].DefaultValue);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                                if ((param.Count != pair.Value.Length) || (matchedArguments != parameters.Count))
                                {
                                    continue;
                                }
                                methodParameters = param.ToArray();
                            }
                            catch (InvalidCastException)
                            {
                                // ignore
                            }
                            methodInfo = pair.Key;
                        }
                    }
                    if ((methodInfo == null) && (Fields != null))
                    {
                        foreach (
                            var field in
                            Fields.Where(info => info.Name.Equals(method, StringComparison.OrdinalIgnoreCase)))
                        {
                            if (parameters.Keys.Contains("value"))
                            {
                                try
                                {
                                    fieldValue = ClassBridge.NormalizeVariable(parameters["value"], field.FieldType,
                                                                               true);
                                }
                                catch (InvalidCastException)
                                {
                                    // ignore
                                }
                            }
                            fieldInfo = field;
                        }
                    }
                }
            }
            if (constructorInfo != null)
            {
                var newObject = constructorInfo.Invoke(methodParameters) as T;
                if (newObject != null)
                {
                    AddInstance(newObject);
                    var instanceId = GlobalPool.GetInstanceId(newObject);
                    if (!string.IsNullOrWhiteSpace(instanceId))
                    {
                        hasResult = true;
                        return(instanceId);
                    }
                }
                return(null);
            }
            if (methodInfo != null)
            {
                if (methodInfo.ReturnType != typeof(void))
                {
                    hasResult = true;
                    return(methodInfo.Invoke(classInstance, methodParameters.ToArray()));
                }
                // Let's not block the UI/Javascript thread if there is no result for the requested method
                Task.Factory.StartNew(() => methodInfo.Invoke(classInstance, methodParameters.ToArray()));
                return(null);
            }
            if (fieldInfo != null)
            {
                if (fieldValue != null)
                {
                    fieldInfo.SetValue(classInstance, fieldValue);
                    return(null);
                }
                hasResult = true;
                return(fieldInfo.GetValue(classInstance));
            }
            return(null);
        }
예제 #5
0
        /// <summary>
        ///     The method to be called when a new message received from the Javascript side
        /// </summary>
        /// <param name="messageString">The message identification string, or string.Empty to match all</param>
        /// <param name="arguments">The message arguments, or null</param>
        /// <returns>Returns the response of the last subscriber</returns>
        protected virtual object OnNewMessage(string messageString, object arguments)
        {
            messageString = messageString.ToLower().Trim();
            object result = null;

            Delegate[] delegates;
            lock (Lock)
            {
                delegates =
                    Subscriptions.Where(
                        pair =>
                        string.IsNullOrEmpty(messageString) || string.IsNullOrEmpty(pair.Key) ||
                        messageString.Equals(pair.Key, StringComparison.CurrentCulture))
                    .SelectMany(pair => pair.Value)
                    .ToArray();
            }
            foreach (var subscription in delegates)
            {
                var methodInfo       = subscription.Method;
                var methodArguments  = new List <object>();
                var methodResultType = methodInfo.ReturnType;
                try
                {
                    var methodParameters = methodInfo.GetParameters();
                    var failed           = false;
                    if (methodParameters.Length > 0)
                    {
                        foreach (var methodParameter in methodParameters)
                        {
                            if (methodArguments.Count == 0 && !(methodParameter.IsOptional && arguments == null))
                            {
                                methodArguments.Add(arguments == null
                                    ? null
                                    : ClassBridge.NormalizeVariable(arguments, methodParameter.ParameterType, true));
                            }
                            else if (methodParameter.IsOptional)
                            {
                                methodArguments.Add(methodParameter.DefaultValue);
                            }
                            else
                            {
                                failed = true;
                                break;
                            }
                        }
                        if (failed)
                        {
                            continue;
                        }
                    }
                }
                catch (Exception)
                {
                    continue;
                }
                if (methodInfo == null)
                {
                    continue;
                }
                if (methodResultType == typeof(void))
                {
                    // If we don't need the result of this method, we better run it in a new thread, so the UI thread don't get blocked
                    Task.Factory.StartNew(() => methodInfo.Invoke(subscription.Target, methodArguments.ToArray()));
                }
                else
                {
                    var methodResult = methodInfo.Invoke(subscription.Target, methodArguments.ToArray());
                    result = methodResult == null
                        ? null
                        : ClassBridge.NormalizeVariable(methodResult, methodResultType, true);
                }
            }
            return(result);
        }