Exemplo n.º 1
0
        public virtual object Convert(object value, Type type, IFormatProvider formatProvider)
        {
            if (value == null)
            {
                if (TypeConverter.TypeIsNullable(type))
                {
                    return(null);
                }

                throw new NotSupportedException(string.Format("Unable to convert null to '{0}'", type.FullName));
            }

            // don't try to convert if value is derived from type
            if (type.IsInstanceOfType(value))
            {
                return(value);
            }

            if (type.IsEnum)
            {
                var integer = System.Convert.ChangeType(value, typeof(int), formatProvider);
                if (integer == null)
                {
                    throw new ArgumentOutOfRangeException();
                }

                return(Enum.ToObject(type, integer));
            }

            var valueType = value.GetType();

            // is the javascript value an ICallable instance ?
            if (valueType == typeof(Func <JsValue, JsValue[], JsValue>))
            {
                var function = (Func <JsValue, JsValue[], JsValue>)value;

                if (type.IsGenericType)
                {
                    var genericType = type.GetGenericTypeDefinition();

                    // create the requested Delegate
                    if (genericType.Name.StartsWith("Action"))
                    {
                        var genericArguments = type.GetGenericArguments();

                        var @params = new ParameterExpression[genericArguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));

                        var callExpresion = Expression.Block(Expression.Call(
                                                                 Expression.Call(Expression.Constant(function.Target),
                                                                                 function.Method,
                                                                                 Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                                                 @vars),
                                                                 typeof(JsValue).GetMethod("ToObject")), Expression.Empty());

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                    else if (genericType.Name.StartsWith("Func"))
                    {
                        var genericArguments = type.GetGenericArguments();
                        var returnType       = genericArguments.Last();

                        var @params = new ParameterExpression[genericArguments.Count() - 1];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));

                        var callExpresion = Expression.Convert(
                            Expression.Call(
                                Expression.Call(Expression.Constant(function.Target),
                                                function.Method,
                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                @vars),
                                typeof(JsValue).GetMethod("ToObject")),
                            returnType);

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                }
                else
                {
                    if (type == typeof(Action))
                    {
                        return((Action)(() => function(JsValue.Undefined, new JsValue[0])));
                    }
                    else if (type.IsSubclassOf(typeof(System.MulticastDelegate)))
                    {
                        var method    = type.GetMethod("Invoke");
                        var arguments = method.GetParameters();

                        var @params = new ParameterExpression[arguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(typeof(object), arguments[i].Name);
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));

                        var callExpression = Expression.Block(
                            Expression.Call(
                                Expression.Call(Expression.Constant(function.Target),
                                                function.Method,
                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                @vars),
                                typeof(JsValue).GetMethod("ToObject")),
                            Expression.Empty());

                        var dynamicExpression = Expression.Invoke(Expression.Lambda(callExpression, new ReadOnlyCollection <ParameterExpression>(@params)), new ReadOnlyCollection <ParameterExpression>(@params));

                        return(Expression.Lambda(type, dynamicExpression, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                }
            }

            return(System.Convert.ChangeType(value, type, formatProvider));
        }
Exemplo n.º 2
0
        public virtual object Convert(object value, Type type, IFormatProvider formatProvider)
        {
            if (value == null)
            {
                if (TypeConverter.TypeIsNullable(type))
                {
                    return(null);
                }

                throw new NotSupportedException(string.Format("Unable to convert null to '{0}'", type.FullName));
            }

            // don't try to convert if value is derived from type
            if (type.IsInstanceOfType(value))
            {
                return(value);
            }

            if (type.IsEnum())
            {
                var integer = System.Convert.ChangeType(value, typeof(int), formatProvider);
                if (integer == null)
                {
                    throw new ArgumentOutOfRangeException();
                }

                return(Enum.ToObject(type, integer));
            }

            var valueType = value.GetType();

            // is the javascript value an ICallable instance ?
            if (valueType == typeof(Func <JsValue, JsValue[], JsValue>))
            {
                var function = (Func <JsValue, JsValue[], JsValue>)value;

                if (type.IsGenericType())
                {
                    var genericType = type.GetGenericTypeDefinition();

                    // create the requested Delegate
                    if (genericType.Name.StartsWith("Action"))
                    {
                        var genericArguments = type.GetGenericArguments();

                        var @params = new ParameterExpression[genericArguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }

                        var tmpVars = new Expression[@params.Length];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            var param = @params[i];
                            if (param.Type.IsValueType())
                            {
                                var boxing = Expression.Convert(param, typeof(object));
                                tmpVars[i] = Expression.Call(null, jsValueFromObject, Expression.Constant(_engine, typeof(Engine)), boxing);
                            }
                            else
                            {
                                tmpVars[i] = Expression.Call(null, jsValueFromObject, Expression.Constant(_engine, typeof(Engine)), param);
                            }
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), tmpVars);

                        var callExpresion = Expression.Block(Expression.Call(
                                                                 Expression.Call(Expression.Constant(function.Target),
                                                                                 function.GetMethodInfo(),
                                                                                 Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                                                 @vars),
                                                                 jsValueToObject), Expression.Empty());

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)).Compile());
                    }
                    else if (genericType.Name.StartsWith("Func"))
                    {
                        var genericArguments = type.GetGenericArguments();
                        var returnType       = genericArguments.Last();

                        var @params = new ParameterExpression[genericArguments.Count() - 1];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }

                        var @vars =
                            Expression.NewArrayInit(typeof(JsValue),
                                                    @params.Select(p =>
                        {
                            var boxingExpression = Expression.Convert(p, typeof(object));
                            return((Expression)Expression.Call(null, jsValueFromObject, Expression.Constant(_engine, typeof(Engine)), boxingExpression));
                        })
                                                    );

                        // the final result's type needs to be changed before casting,
                        // for instance when a function returns a number (double) but C# expects an integer

                        var callExpresion = Expression.Convert(
                            Expression.Call(null,
                                            convertChangeType,
                                            Expression.Call(
                                                Expression.Call(Expression.Constant(function.Target),
                                                                function.GetMethodInfo(),
                                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                                @vars),
                                                jsValueToObject),
                                            Expression.Constant(returnType, typeof(Type)),
                                            Expression.Constant(System.Globalization.CultureInfo.InvariantCulture, typeof(IFormatProvider))
                                            ),
                            returnType);

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)).Compile());
                    }
                }
                else
                {
                    if (type == typeof(Action))
                    {
                        return((Action)(() => function(JsValue.Undefined, new JsValue[0])));
                    }
                    else if (typeof(MulticastDelegate).IsAssignableFrom(type))
                    {
                        var method    = type.GetMethod("Invoke");
                        var arguments = method.GetParameters();

                        var @params = new ParameterExpression[arguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(typeof(object), arguments[i].Name);
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => (Expression)Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));

                        var callExpression = Expression.Block(
                            Expression.Call(
                                Expression.Call(Expression.Constant(function.Target),
                                                function.GetMethodInfo(),
                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                @vars),
                                typeof(JsValue).GetMethod("ToObject")),
                            Expression.Empty());

                        var dynamicExpression = Expression.Invoke(Expression.Lambda(callExpression, new ReadOnlyCollection <ParameterExpression>(@params)), new ReadOnlyCollection <Expression>(@params));

                        return(Expression.Lambda(type, dynamicExpression, new ReadOnlyCollection <ParameterExpression>(@params)).Compile());
                    }
                }
            }

            if (type.IsArray)
            {
                var source = value as object[];
                if (source == null)
                {
                    throw new ArgumentException(String.Format("Value of object[] type is expected, but actual type is {0}.", value.GetType()));
                }

                var targetElementType = type.GetElementType();
                var itemsConverted    = source.Select(o => Convert(o, targetElementType, formatProvider)).ToArray();
                var result            = Array.CreateInstance(targetElementType, source.Length);
                itemsConverted.CopyTo(result, 0);
                return(result);
            }

            if (type.IsGenericType() && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                type = Nullable.GetUnderlyingType(type);
            }

            return(System.Convert.ChangeType(value, type, formatProvider));
        }
Exemplo n.º 3
0
        public virtual object Convert(object value, Type type, IFormatProvider formatProvider)
        {
            if (value == null)
            {
                if (TypeConverter.TypeIsNullable(type))
                {
                    return(null);
                }

                throw new NotSupportedException(string.Format("Unable to convert null to '{0}'", type.FullName));
            }

            // don't try to convert if value is derived from type
            if (type.IsInstanceOfType(value))
            {
                return(value);
            }

            var expando = value as ExpandoObject;

            if (expando != null)
            {
                var inst = Activator.CreateInstance(type);
                foreach (var kv in expando)
                {
                    var property = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public).Where(p => ObjectWrapper.EqualsIgnoreCasing(p.Name, kv.Key)).FirstOrDefault();
                    if (property != null)
                    {
                        property.SetValue(inst, kv.Value, null);
                    }
                    else
                    {
                        var field = type.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public).Where(f => ObjectWrapper.EqualsIgnoreCasing(f.Name, kv.Key)).FirstOrDefault();
                        if (field != null)
                        {
                            field.SetValue(inst, kv.Value);
                        }
                    }
                }
                return(inst);
            }

            if (type.IsEnum)
            {
                var integer = System.Convert.ChangeType(value, typeof(int), formatProvider);
                if (integer == null)
                {
                    throw new ArgumentOutOfRangeException();
                }

                return(Enum.ToObject(type, integer));
            }

            var valueType = value.GetType();

            // is the javascript value an ICallable instance ?
            if (valueType == typeof(Func <JsValue, JsValue[], JsValue>))
            {
                var function = (Func <JsValue, JsValue[], JsValue>)value;

                if (type.IsGenericType)
                {
                    var genericType = type.GetGenericTypeDefinition();

                    // create the requested Delegate
                    if (genericType.Name.StartsWith("Action"))
                    {
                        var genericArguments = type.GetGenericArguments();

                        var @params = new ParameterExpression[genericArguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }

                        var engine = Expression.Constant(_engine, typeof(Engine));
                        var @vars  = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, jsValueFromObject, engine, Expression.Convert(p, typeof(object)))));

                        var callExpresion = Expression.Block(Expression.Call(
                                                                 Expression.Call(Expression.Constant(function.Target),
                                                                                 function.Method,
                                                                                 Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                                                 @vars),
                                                                 jsValueToObject), Expression.Empty());

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                    else if (genericType.Name.StartsWith("Func"))
                    {
                        var genericArguments = type.GetGenericArguments();
                        var returnType       = genericArguments.Last();

                        var @params = new ParameterExpression[genericArguments.Count() - 1];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
                        }

                        var @vars =
                            Expression.NewArrayInit(typeof(JsValue),
                                                    @params.Select(p =>
                        {
                            var boxingExpression = Expression.Convert(p, typeof(object));
                            return(Expression.Call(null, jsValueFromObject, Expression.Constant(_engine, typeof(Engine)), boxingExpression));
                        })
                                                    );

                        // the final result's type needs to be changed before casting,
                        // for instance when a function returns a number (double) but C# expects an integer

                        var callExpresion = Expression.Convert(
                            Expression.Call(null,
                                            convertChangeType,
                                            Expression.Call(
                                                Expression.Call(Expression.Constant(function.Target),
                                                                function.Method,
                                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                                @vars),
                                                jsValueToObject),
                                            Expression.Constant(returnType, typeof(Type)),
                                            Expression.Constant(System.Globalization.CultureInfo.InvariantCulture, typeof(IFormatProvider))
                                            ),
                            returnType);

                        return(Expression.Lambda(callExpresion, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                }
                else
                {
                    if (type == typeof(Action))
                    {
                        return((Action)(() => function(JsValue.Undefined, new JsValue[0])));
                    }
                    else if (type.IsSubclassOf(typeof(System.MulticastDelegate)))
                    {
                        var method    = type.GetMethod("Invoke");
                        var arguments = method.GetParameters();

                        var @params = new ParameterExpression[arguments.Count()];
                        for (var i = 0; i < @params.Count(); i++)
                        {
                            @params[i] = Expression.Parameter(typeof(object), arguments[i].Name);
                        }
                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));

                        var callExpression = Expression.Block(
                            Expression.Call(
                                Expression.Call(Expression.Constant(function.Target),
                                                function.Method,
                                                Expression.Constant(JsValue.Undefined, typeof(JsValue)),
                                                @vars),
                                typeof(JsValue).GetMethod("ToObject")),
                            Expression.Empty());

                        var dynamicExpression = Expression.Invoke(Expression.Lambda(callExpression, new ReadOnlyCollection <ParameterExpression>(@params)), new ReadOnlyCollection <ParameterExpression>(@params));

                        return(Expression.Lambda(type, dynamicExpression, new ReadOnlyCollection <ParameterExpression>(@params)));
                    }
                }
            }

            if (type.IsArray)
            {
                var source = value as object[];
                if (source == null)
                {
                    throw new ArgumentException(String.Format("Value of object[] type is expected, but actual type is {0}.", value.GetType()));
                }

                var targetElementType = type.GetElementType();
                var itemsConverted    = source.Select(o => Convert(o, targetElementType, formatProvider)).ToArray();
                var result            = Array.CreateInstance(targetElementType, source.Length);
                itemsConverted.CopyTo(result, 0);
                return(result);
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(JsList <>))
            {
                var items     = (object[])value;
                var finalType = type.GetGenericArguments()[0];
                var objArr    = items;
                var arr       = Array.CreateInstance(finalType, objArr.Length);
                Array.Copy(objArr, arr, objArr.Length);

                var cc = Activator.CreateInstance(type);
                cc.GetType().GetMethod("AddRange").Invoke(cc, new[] { arr });
                return(cc);
            }

            try
            {
                return(System.Convert.ChangeType(value, type, formatProvider));
            }
            catch (Exception ex)
            {
                throw new Exception("Cannot convert type " + value.GetType().FullName + " to type " + type.FullName);
            }
        }