示例#1
0
        /// <summary>
        /// Binds all the fields for the instance.
        /// </summary>
        private void BindFields(JsBinding binding, IHostType hostType, object instance)
        {
            // TODO: Seems like we can hoist this into JsInterop, which would allow us refactor
            // TODO: out the builder class completely.
            var fields = hostType.FieldNames;

            for (int i = 0; i < fields.Count; ++i)
            {
                var fieldName = fields[i];

                binding.AddProperty(
                    fieldName,
                    (v, s, args, argLength, data) =>
                {
                    var fieldInfo = hostType.FieldFor(fieldName).Field;
                    var result    = fieldInfo.GetValue(instance);

                    var returnType = JsConversions.TypeFor(result, fieldInfo.FieldType);
                    return(_interop.ToJsObject(result, returnType));
                },
                    (v, s, args, argLength, data) =>
                {
                    var fieldInfo = hostType.FieldFor(fieldName).Field;
                    var fieldType = fieldInfo.FieldType;

                    var value = _interop.ToHostObject(args[1], fieldType);
                    fieldInfo.SetValue(instance, value);

                    return(JavaScriptValue.Invalid);
                });
            }
        }
示例#2
0
        /// <summary>
        /// Binds all public properties for the instance.
        /// </summary>
        private void BindProperties(JsBinding binding, IHostType hostType, object instance)
        {
            // TODO: Seems like we can hoist this into JsInterop, which would allow us refactor
            // TODO: out the builder class completely.
            var properties = hostType.PropertyNames;

            for (int i = 0; i < properties.Count; ++i)
            {
                var propertyName = properties[i];

                binding.AddProperty(
                    propertyName,
                    (v, s, args, argLength, data) =>
                {
                    var get    = hostType.PropertyFor(propertyName).Getter;
                    var result = get.Invoke(instance, EmptyParameters);

                    var returnType = JsConversions.TypeFor(result, get.ReturnType);
                    return(_interop.ToJsObject(result, returnType));
                },
                    (v, s, args, argLength, data) =>
                {
                    var hostProperty = hostType.PropertyFor(propertyName);
                    var propType     = hostProperty.PropertyType;
                    var set          = hostProperty.Setter;

                    var value = _interop.ToHostObject(args[1], propType);
                    set.Invoke(instance, new[] { value });
                    return(JavaScriptValue.Invalid);
                });
            }
        }
示例#3
0
        /// <summary>
        /// Sets the host object to target when creating the binding.
        /// </summary>
        /// <param name="hostObject">The host object to use for the javascript binding.</param>
        /// <param name="type">The <see cref="Type"/> of the host object.</param>
        public JsBindingBuilder BoundTo(object hostObject, Type type)
        {
            _boundTo  = hostObject;
            _hostType = TypeCache.Get(type);

            return(this);
        }
示例#4
0
        /// <summary>
        /// Adds function bindings for all methods in the <see cref="IHostType"/>.
        /// </summary>
        private void BindMethods(JsBinding binding, IHostType hostType, object instance)
        {
            // TODO: Seems like we can hoist this into JsInterop, which would allow us refactor
            // TODO: out the builder class completely.
            var methods = hostType.MethodNames;

            for (int i = 0; i < methods.Count; ++i)
            {
                var methodName = methods[i];

                binding.AddFunction(
                    methodName,
                    (v, s, args, argLength, data) =>
                {
                    var totalParameters = argLength - 1;
                    var hostMethods     = hostType.MethodsFor(methodName, totalParameters);
                    if (hostMethods.Count == 0)
                    {
                        var message = $"Calling host function that does not exist: [Method: {methodName}, Instance: {instance}]";
                        JsErrorHelper.SetJsException(message);
                        return(JavaScriptValue.Invalid);
                    }

                    HostMethod hostMethodInfo;

                    // Only a single method returned. Call this optimistically
                    if (hostMethods.Count == 1)
                    {
                        hostMethodInfo = hostMethods[0];
                    }
                    else
                    {
                        // Get the Parameter Key, and look up cached invocation
                        var invokeKey = JsConversions.ToInvokeKey(methodName, args, argLength);
                        if (!hostType.TryGetInvocation(invokeKey, out hostMethodInfo))
                        {
                            // Otherwise, locate best method for these argument, and cache
                            hostMethodInfo = FindBestMethod(hostMethods, args, argLength);
                            hostType.CacheInvocation(invokeKey, hostMethodInfo);
                        }
                    }

                    if (null == hostMethodInfo)
                    {
                        LogMethodSelectionFailure(hostMethods, args, argLength);
                        JsErrorHelper.SetJsException(
                            $"Calling host function that does not exist: [Method: {methodName}, Instance: {instance}]");
                        return(JavaScriptValue.Invalid);
                    }

                    try
                    {
                        var realParams = ToParameters(hostMethodInfo, args, argLength);

                        var result     = hostMethodInfo.Method.Invoke(instance, realParams);
                        var resultType = hostMethodInfo.ReturnType;
                        if (resultType == typeof(void))
                        {
                            return(JavaScriptValue.Invalid);
                        }

                        resultType = JsConversions.TypeFor(result, resultType);
                        return(_interop.ToJsObject(result, resultType));
                    }
                    catch (Exception e)
                    {
                        LogMethodInvocationInfo(hostMethodInfo, instance);

                        throw;
                    }
                });
            }
        }