Beispiel #1
0
        public static BasicTypes GetConversionType(Type innType, Type outType)
        {
            if (innType.Implements<IDictionary>() && outType.Implements<IDictionary>())
                return BasicTypes.Dictionary;
            if (innType.Implements<IEnumerable>() && outType.Implements<IEnumerable>() && !innType.IsValueType())
                return BasicTypes.List;
            if (innType.IsValueType() && outType.IsValueType() || TypeExtensions.CanConvert(outType, innType))
                return BasicTypes.Convertable;
            return BasicTypes.ComplexType;

        }
        public static object TryCast(object value, Type targetType) {
            Type underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;
#if !NETFX_CORE
            if(underlyingType.IsEnum && value is string) {
#else
            if(underlyingType.IsEnum() && value is string) {
#endif
                value = Enum.Parse(underlyingType, (string)value, false);
            } else if(
#if !NETFX_CORE
                value is IConvertible &&
#else
                IsConvertableType(value) &&
#endif
                !targetType.IsAssignableFrom(value.GetType())) {
                value = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
            }
#if !NETFX_CORE
            if(value == null && targetType.IsValueType)
#else
            if(value == null && targetType.IsValueType())
#endif
                value = Activator.CreateInstance(targetType);
            return value;
        }
        public static object DeserializeFromString(string reader, Type type, Options options)
        {
            var cached = (Func<string, Options, object>)DeserializeFromStringIndirectCache[type];
            if (cached == null)
            {
                lock (DeserializeFromStreamIndirectCache)
                {
                    cached = (Func<string, Options, object>)DeserializeFromStringIndirectCache[type];
                    if (cached == null)
                    {
                        var emit = Emit.NewDynamicMethod(typeof(object), new[] { typeof(string), typeof(Options) }, doVerify: Utils.DoVerify);
                        var mtd = JSONDeserializeFromString.MakeGenericMethod(type);

                        emit.LoadArgument(0);   // TextReader
                        emit.LoadArgument(1);   // TextReader Options
                        emit.Call(mtd);         // type
                        if (type.IsValueType())
                        {
                            emit.Box(type);     // object
                        }
                        emit.Return();

                        DeserializeFromStringIndirectCache[type] = cached = emit.CreateDelegate<Func<string, Options, object>>(Utils.DelegateOptimizationOptions);
                    }
                }
            }

            return cached(reader, options);
        }
Beispiel #4
0
        public static Instruction Create(Type type)
        {
            // Boxed enums can be unboxed as their underlying types:
            switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) {
                case TypeCode.Boolean: return _Boolean ?? (_Boolean = new NotEqualBoolean());
                case TypeCode.SByte: return _SByte ?? (_SByte = new NotEqualSByte());
                case TypeCode.Byte: return _Byte ?? (_Byte = new NotEqualByte());
                case TypeCode.Char: return _Char ?? (_Char = new NotEqualChar());
                case TypeCode.Int16: return _Int16 ?? (_Int16 = new NotEqualInt16());
                case TypeCode.Int32: return _Int32 ?? (_Int32 = new NotEqualInt32());
                case TypeCode.Int64: return _Int64 ?? (_Int64 = new NotEqualInt64());

                case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new NotEqualInt16());
                case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new NotEqualInt32());
                case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new NotEqualInt64());

                case TypeCode.Single: return _Single ?? (_Single = new NotEqualSingle());
                case TypeCode.Double: return _Double ?? (_Double = new NotEqualDouble());

                case TypeCode.Object:
                    if (!type.IsValueType()) {
                        return _Reference ?? (_Reference = new NotEqualReference());
                    }
                    // TODO: Nullable<T>
                    throw new NotImplementedException();

                default:
                    throw new NotImplementedException();
            }
        }
 public static void UnboxIfNeeded(this ILGenerator generator, Type type)
 {
   if (type.IsValueType())
     generator.Emit(OpCodes.Unbox_Any, type);
   else
     generator.Emit(OpCodes.Castclass, type);
 }
Beispiel #6
0
 public static object CreateNonNullValue(Type type)
 {
     return type.IsValueType()
         ? CreateObject(type)
         : type == typeof (string)
             ? string.Empty
             : CreateObject(type);
 }
 public static void PushInstance(this ILGenerator generator, Type type)
 {
   generator.Emit(OpCodes.Ldarg_0);
   if (type.IsValueType())
     generator.Emit(OpCodes.Unbox, type);
   else
     generator.Emit(OpCodes.Castclass, type);
 }
Beispiel #8
0
        /// <summary>Checks whether the specified <paramref name='type' /> can be assigned null.</summary>
        /// <param name='type'>Type to check.</param>
        /// <returns>true if type is a reference type or a Nullable type; false otherwise.</returns>
        internal static bool TypeAllowsNull(Type type)
        {
            Debug.Assert(type != null, "type != null");

            //// This is a copy of WebUtil.TypeAllowsNull from the product.

            return !type.IsValueType() || IsNullableType(type);
        }
Beispiel #9
0
 internal static bool TypeAllowsNull(Type type)
 {
     if (type.IsValueType())
     {
         return IsNullableType(type);
     }
     return true;
 }
 public static void BoxIfNeeded(this ILGenerator generator, Type type)
 {
     if (type.IsValueType())
     {
         generator.Emit(OpCodes.Box, type);
     }
     else
     {
         generator.Emit(OpCodes.Castclass, type);
     }
 }
Beispiel #11
0
 static LambdaExpression ConvertExpression(Type sourceType, Type destinationType)
 {
     bool nullableDestination;
     var underlyingDestinationType = UnderlyingType(destinationType, out nullableDestination);
     var convertMethod = typeof(Convert).GetDeclaredMethod("To" + underlyingDestinationType.Name, new[] { sourceType });
     var sourceParameter = Parameter(sourceType, "source");
     Expression convertCall = Call(convertMethod, sourceParameter);
     var lambdaBody = nullableDestination && !sourceType.IsValueType() ?
                                     Condition(Equal(sourceParameter, Constant(null)), Constant(null, destinationType), ToType(convertCall, destinationType)) :
                                     convertCall;
     return Lambda(lambdaBody, sourceParameter);
 }
Beispiel #12
0
 static void EmitTypeConversion(ILGenerator generator, Type castType, bool isContainer)
 {
     if (castType == typeof(object))
     {
     }
     else if (castType.IsValueType())
     {
         generator.Emit(isContainer ? OpCodes.Unbox : OpCodes.Unbox_Any, castType);
     }
     else
     {
         generator.Emit(OpCodes.Castclass, castType);
     }
 }
Beispiel #13
0
 /// <summary>
 /// Converts an object at runtime into the specified type.
 /// </summary>
 public virtual object Convert(object obj, Type toType) {
     if (obj == null) {
         if (!toType.IsValueType()) {
             return null;
         }
     } else {
         if (toType.IsValueType()) {
             if (toType == obj.GetType()) {
                 return obj;
             }
         } else {
             if (toType.IsAssignableFrom(obj.GetType())) {
                 return obj;
             }
         }
     }
     throw Error.InvalidCast(obj != null ? obj.GetType().Name : "(null)", toType.Name);
 }
Beispiel #14
0
        public object GetValue(Type targetType)
        {
            var stringValue = _underlyingValue as string;
            if (_underlyingValue == null)
            {
                if (targetType.IsValueType() && !(targetType.IsGenericType() && targetType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {
                    var valueAsString = string.IsNullOrEmpty(stringValue) ? "<null>" : string.Format("\"{0}\"", _underlyingValue);
                    throw new ArgumentException(string.Format("Cannot convert {0} to {1} (Column: '{2}', Row: {3})", valueAsString, targetType.Name, Header, Row));
                }

                ValueHasBeenUsed = true;
                return null;
            }

            ValueHasBeenUsed = true;
            if (targetType.IsInstanceOfType(_underlyingValue))
                return _underlyingValue;

            if (targetType.IsEnum() && _underlyingValue is string)
                return Enum.Parse(targetType, (string)_underlyingValue);

            if (targetType == typeof(DateTime))
                return DateTime.Parse(stringValue);

            try
            {
                return Convert.ChangeType(_underlyingValue, targetType);
            }
            catch (InvalidCastException ex)
            {
                throw new UnassignableExampleException(string.Format(
                    "{0} cannot be assigned to {1} (Column: '{2}', Row: {3})", 
                    _underlyingValue == null ? "<null>" : _underlyingValue.ToString(),
                    targetType.Name, Header, Row), ex, this);
            }
        }
Beispiel #15
0
        /// <summary>
        ///   Emits a load indirect opcode of the appropriate type for a value or object reference.
        ///   Pops a pointer off the evaluation stack, dereferences it and loads
        ///   a value of the specified type.
        /// </summary>
        /// <param name = "gen"></param>
        /// <param name = "type"></param>
        public static void EmitLoadIndirectOpCodeForType(ILGenerator gen, Type type)
        {
            if (type.IsEnum())
            {
                EmitLoadIndirectOpCodeForType(gen, GetUnderlyingTypeOfEnum(type));
                return;
            }

            if (type.IsByRef)
            {
                throw new NotSupportedException("Cannot load ByRef values");
            }
            else if (type.IsPrimitive() && type != typeof(IntPtr))
            {
                var opCode = LdindOpCodesDictionary.Instance[type];

                if (opCode == LdindOpCodesDictionary.EmptyOpCode)
                {
                    throw new ArgumentException("Type " + type + " could not be converted to a OpCode");
                }

                gen.Emit(opCode);
            }
            else if (type.IsValueType())
            {
                gen.Emit(OpCodes.Ldobj, type);
            }
            else if (type.IsGenericParameter)
            {
                gen.Emit(OpCodes.Ldobj, type);
            }
            else
            {
                gen.Emit(OpCodes.Ldind_Ref);
            }
        }
Beispiel #16
0
 private static bool IsTypeNullable(Type type)
 {
     return !type.IsValueType() ||
            (type.IsGenericType() &&
             type.GetGenericTypeDefinition() == typeof(Nullable<>));
 }
        internal static bool IsCompatibleWith(this Type source, Type target, out bool boxRequired)
        {
            boxRequired = false;
            if (source == target)
                return true;
            if (!target.IsValueType())
            {
                boxRequired = source.IsValueType();
                return target.IsAssignableFrom(source);
            }

            Type st = GetNonNullableType(source);
            Type tt = GetNonNullableType(target);
            if (st != source && tt.Equals(st))
                return false;
            TypeCode sc = st.IsEnum() ? TypeCode.Object : st.GetTypeCode();
            TypeCode tc = tt.IsEnum() ? TypeCode.Object : tt.GetTypeCode();
            switch (sc)
            {
                case TypeCode.SByte:
                    switch (tc)
                    {
                        case TypeCode.SByte:
                        case TypeCode.Int16:
                        case TypeCode.Int32:
                        case TypeCode.Int64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.Byte:
                    switch (tc)
                    {
                        case TypeCode.Byte:
                        case TypeCode.Int16:
                        case TypeCode.UInt16:
                        case TypeCode.Int32:
                        case TypeCode.UInt32:
                        case TypeCode.Int64:
                        case TypeCode.UInt64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.Int16:
                    switch (tc)
                    {
                        case TypeCode.Int16:
                        case TypeCode.Int32:
                        case TypeCode.Int64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.UInt16:
                    switch (tc)
                    {
                        case TypeCode.UInt16:
                        case TypeCode.Int32:
                        case TypeCode.UInt32:
                        case TypeCode.Int64:
                        case TypeCode.UInt64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.Int32:
                    switch (tc)
                    {
                        case TypeCode.Int32:
                        case TypeCode.Int64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.UInt32:
                    switch (tc)
                    {
                        case TypeCode.UInt32:
                        case TypeCode.Int64:
                        case TypeCode.UInt64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.Int64:
                    switch (tc)
                    {
                        case TypeCode.Int64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.UInt64:
                    switch (tc)
                    {
                        case TypeCode.UInt64:
                        case TypeCode.Single:
                        case TypeCode.Double:
                        case TypeCode.Decimal:
                            return true;
                    }
                    break;
                case TypeCode.Single:
                    switch (tc)
                    {
                        case TypeCode.Single:
                        case TypeCode.Double:
                            return true;
                    }
                    break;
                default:
                    if (st == tt)
                        return true;
                    break;
            }
            return false;
        }
 private static object GetDefault(Type type)
 {
     return type.IsValueType() ? Activator.CreateInstance(type) : null;
 }
Beispiel #19
0
 internal static bool CanAssign(Type/*!*/ to, Type/*!*/ from)
 {
     return to.IsAssignableFrom(from) && (to.IsValueType() == from.IsValueType());
 }
Beispiel #20
0
        /*!*/
        public override Expression Convert(DynamicMetaObject/*!*/ metaObject, Type restrictedType, ParameterInfo info, Type/*!*/ toType)
        {
            Expression expr = metaObject.Expression;
            Type fromType = restrictedType ?? expr.Type;

            // block:
            if (fromType == typeof(MissingBlockParam)) {
                Debug.Assert(toType == typeof(BlockParam) || toType == typeof(MissingBlockParam));
                return AstUtils.Constant(null);
            }

            if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) {
                return AstUtils.Constant(null);
            }

            // protocol conversions:
            if (info != null && info.IsDefined(typeof(DefaultProtocolAttribute), false)) {
                var action = RubyConversionAction.TryGetDefaultConversionAction(Context, toType);
                if (action != null) {
                    // TODO: inline implicit conversions:
                    return AstUtils.LightDynamic(action, toType, expr);
                }

                // Do not throw an exception here to allow generic type parameters to be used with D.P. attribute.
                // The semantics should be to use DP if available for the current instantiation and ignore it otherwise.
            }

            if (restrictedType != null) {
                if (restrictedType == typeof(DynamicNull)) {
                    if (!toType.IsValueType() || toType.IsGenericType() && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
                        return AstUtils.Constant(null, toType);
                    } else if (toType == typeof(bool)) {
                        return AstUtils.Constant(false);
                    }
                }

                if (toType.IsAssignableFrom(restrictedType)) {
                    // expr can be converted to restrictedType, which can be converted toType => we can convert expr to toType:
                    return AstUtils.Convert(expr, CompilerHelpers.GetVisibleType(toType));
                }

                // if there is a simple conversion from restricted type, convert the expression to the restricted type and use that conversion:
                Type visibleRestrictedType = CompilerHelpers.GetVisibleType(restrictedType);
                if (Converter.CanConvertFrom(metaObject, visibleRestrictedType, toType, false, NarrowingLevel.None, false, false).IsConvertible) {
                    expr = AstUtils.Convert(expr, visibleRestrictedType);
                }
            }

            return Converter.ConvertExpression(expr, toType, _args.RubyContext, _args.MetaContext.Expression, _implicitProtocolConversions);
        }
Beispiel #21
0
        internal static BuiltinFunction GetConstructorFunction(Type type, string name) {
            List<MethodBase> methods = new List<MethodBase>();
            bool hasDefaultConstructor = false;

            foreach (ConstructorInfo ci in type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)) {
                if (ci.IsPublic) {
                    if (ci.GetParameters().Length == 0) {
                        hasDefaultConstructor = true;
                    }

                    methods.Add(ci);
                }
            }
            
            if (type.IsValueType() && !hasDefaultConstructor && type != typeof(void)) {
                try {
                    methods.Add(typeof(ScriptingRuntimeHelpers).GetMethod("CreateInstance", ReflectionUtils.EmptyTypes).MakeGenericMethod(type));
                } catch (BadImageFormatException) {
                    // certain types (e.g. ArgIterator) won't survive the above call.
                    // we won't let you create instances of these types.
                }
            }

            if (methods.Count > 0) {
                return BuiltinFunction.MakeFunction(name, methods.ToArray(), type);
            }

            return null;
        }
Beispiel #22
0
        internal static Convertibility CanConvertFrom(DynamicMetaObject fromArg, Type/*!*/ fromType, Type/*!*/ toType, bool toNotNullable,
            NarrowingLevel level, bool explicitProtocolConversions, bool implicitProtocolConversions)
        {
            ContractUtils.RequiresNotNull(fromType, "fromType");
            ContractUtils.RequiresNotNull(toType, "toType");

            var metaConvertible = fromArg as IConvertibleMetaObject;
            var rubyMetaConvertible = fromArg as IConvertibleRubyMetaObject;

            //
            // narrowing level 0:
            //

            if (toType == fromType) {
                return Convertibility.AlwaysConvertible;
            }

            if (fromType == typeof(DynamicNull)) {
                if (toNotNullable) {
                    return Convertibility.NotConvertible;
                }

                if (toType.IsGenericType() && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
                    return Convertibility.AlwaysConvertible;
                }

                if (!toType.IsValueType()) {
                    // null convertible to any reference type:
                    return Convertibility.AlwaysConvertible;
                } else if (toType == typeof(bool)) {
                    return Convertibility.AlwaysConvertible;
                } else if (!ProtocolConversionAction.HasDefaultConversion(toType)) {
                    // null not convertible to a value type unless a protocol conversion is allowed:
                    return Convertibility.NotConvertible;
                }
            }

            // blocks:
            if (fromType == typeof(MissingBlockParam)) {
                return new Convertibility(toType == typeof(BlockParam) && !toNotNullable, null);
            }

            if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) {
                return Convertibility.AlwaysConvertible;
            }

            if (toType.IsAssignableFrom(fromType)) {
                return Convertibility.AlwaysConvertible;
            }

            if (HasImplicitNumericConversion(fromType, toType)) {
                return Convertibility.AlwaysConvertible;
            }

            if (CompilerHelpers.GetImplicitConverter(fromType, toType) != null) {
                return Convertibility.AlwaysConvertible;
            }

            if (rubyMetaConvertible != null) {
                return rubyMetaConvertible.IsConvertibleTo(toType, false);
            } else if (metaConvertible != null) {
                return new Convertibility(metaConvertible.CanConvertTo(toType, false), null);
            }

            //
            // narrowing level 1:
            //

            if (level < NarrowingLevel.One) {
                return Convertibility.NotConvertible;
            }

            if (explicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) {
                return Convertibility.AlwaysConvertible;
            }

            //
            // narrowing level 2:
            //

            if (level < NarrowingLevel.Two) {
                return Convertibility.NotConvertible;
            }

            if (HasExplicitNumericConversion(fromType, toType)) {
                return Convertibility.AlwaysConvertible;
            }

            if (CompilerHelpers.GetExplicitConverter(fromType, toType) != null) {
                return Convertibility.AlwaysConvertible;
            }

            if (CompilerHelpers.HasTypeConverter(fromType, toType)) {
                return Convertibility.AlwaysConvertible;
            }

            if (fromType == typeof(char) && toType == typeof(string)) {
                return Convertibility.AlwaysConvertible;
            }

            if (toType == typeof(bool)) {
                return Convertibility.AlwaysConvertible;
            }

            if (rubyMetaConvertible != null) {
                return rubyMetaConvertible.IsConvertibleTo(toType, true);
            } else if (metaConvertible != null) {
                return new Convertibility(metaConvertible.CanConvertTo(toType, true), null);
            }

            //
            // narrowing level 3:
            //

            if (level < NarrowingLevel.Three) {
                return Convertibility.NotConvertible;
            }

            if (implicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) {
                return Convertibility.AlwaysConvertible;
            }

            // A COM object can potentially be converted to the given interface, but might also be not so use this only as the last resort:
            if (TypeUtils.IsComObjectType(fromType) && toType.IsInterface()) {
                return Convertibility.AlwaysConvertible;
            }

            return Convertibility.NotConvertible;
        }
Beispiel #23
0
 public static object CreateDefaultValue(Type type)
 {
     return type.IsValueType() ? CreateObject(type) : null;
 }
Beispiel #24
0
 private static bool CompatibleParameterTypes(Type parameter, Type argument)
 {
     if (parameter == argument ||
         (!parameter.IsValueType() && !argument.IsValueType() && parameter.IsAssignableFrom(argument))) {
         return true;
     }
     if (parameter.IsByRef && parameter.GetElementType() == argument) {
         return true;
     }
     return false;
 }
Beispiel #25
0
        internal static Expression ExplicitConvert(Expression/*!*/ expr, Type/*!*/ fromType, Type/*!*/ toType)
        {
            expr = AstUtils.Convert(expr, fromType);

            if (HasExplicitNumericConversion(fromType, toType)) {
                // special cases to mimic Ruby behavior precisely:
                if (fromType == typeof(BigInteger)) {
                    if (toType == typeof(int)) {
                        return Methods.ConvertBignumToFixnum.OpCall(expr);
                    } else if (toType == typeof(double)) {
                        return Methods.ConvertBignumToFloat.OpCall(expr);
                    }
                } else if (fromType == typeof(double) && toType == typeof(int)) {
                    return Methods.ConvertDoubleToFixnum.OpCall(expr);
                }

                return Ast.ConvertChecked(expr, toType);
            }

            MethodInfo converter = CompilerHelpers.GetExplicitConverter(fromType, toType);
            if (converter != null) {
                return Ast.Call(null, converter, expr);
            }

            if (fromType == typeof(char) && toType == typeof(string)) {
                return Ast.Call(null, fromType.GetMethod("ToString", BindingFlags.Public | BindingFlags.Static), expr);
            }

            if (toType == typeof(bool)) {
                Debug.Assert(fromType != typeof(bool));
                return fromType.IsValueType() ? AstUtils.Constant(true) : Ast.NotEqual(expr, AstUtils.Constant(null));
            }

            // TODO:
            //if (TypeConverter...(fromType, toType)) {
            //    return true;
            //}

            return null;
        }
		internal object CoerceType(Type targetType, object value)
		{
			bool isNullable = TypeCoercionUtility.IsNullable(targetType);
			if (value == null)
			{
#if NETFX_CORE
                if (!allowNullValueTypes &&
                    targetType.IsValueType() &&
                    !isNullable)
#else
				if (!allowNullValueTypes &&
					targetType.IsValueType &&
					!isNullable)
#endif
				{
					throw new JsonTypeCoercionException(String.Format(TypeCoercionUtility.ErrorNullValueType, targetType.FullName));
				}
				return value;
			}

			if (isNullable)
			{
				// nullable types have a real underlying struct
				Type[] genericArgs = targetType.GetGenericArguments();
				if (genericArgs.Length == 1)
				{
					targetType = genericArgs[0];
				}
			}

			Type actualType = value.GetType();
			if (targetType.IsAssignableFrom(actualType))
			{
				return value;
			}

#if NETFX_CORE
            if (targetType.IsEnum())
#else
            if (targetType.IsEnum)
#endif
			{
				if (value is String)
				{
					if (!Enum.IsDefined(targetType, value))
					{
						// if isn't a defined value perhaps it is the JsonName
						foreach (FieldInfo field in targetType.GetFields())
						{
							string jsonName = JsonNameAttribute.GetJsonName(field);
							if (((string)value).Equals(jsonName))
							{
								value = field.Name;
								break;
							}
						}
					}

					return Enum.Parse(targetType, (string)value);
				}
				else
				{
					value = this.CoerceType(Enum.GetUnderlyingType(targetType), value);
					return Enum.ToObject(targetType, value);
				}
			}

			if (value is IDictionary)
			{
				Dictionary<string, MemberInfo> memberMap;
				return this.CoerceType(targetType, (IDictionary)value, out memberMap);
			}

			if (typeof(IEnumerable).IsAssignableFrom(targetType) &&
				typeof(IEnumerable).IsAssignableFrom(actualType))
			{
				return this.CoerceList(targetType, actualType, (IEnumerable)value);
			}

			if (value is String)
			{
				if (targetType == typeof(DateTime))
				{
					DateTime date;
					if (DateTime.TryParse(
						(string)value,
						DateTimeFormatInfo.InvariantInfo,
						DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault,
						out date))
					{
						return date;
					}
				}
				else if (targetType == typeof(Guid))
				{
					// try-catch is pointless since will throw upon generic conversion
					return new Guid((string)value);
				}
				else if (targetType == typeof(Char))
				{
					if (((string)value).Length == 1)
					{
						return ((string)value)[0];
					}
				}
				else if (targetType == typeof(Uri))
				{
					Uri uri;
					if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out uri))
					{
						return uri;
					}
				}
				else if (targetType == typeof(Version))
				{
					// try-catch is pointless since will throw upon generic conversion
					return new Version((string)value);
				}
			}
			else if (targetType == typeof(TimeSpan))
			{
				return new TimeSpan((long)this.CoerceType(typeof(Int64), value));
            }

#if !NETFX_CORE
            TypeConverter converter = TypeDescriptor.GetConverter(targetType);
			if (converter.CanConvertFrom(actualType))
			{
				return converter.ConvertFrom(value);
			}

			converter = TypeDescriptor.GetConverter(actualType);
			if (converter.CanConvertTo(targetType))
			{
				return converter.ConvertTo(value, targetType);
			}
#endif

			try
			{
				// fall back to basics
				return Convert.ChangeType(value, targetType);
			}
			catch (Exception ex)
			{
				throw new JsonTypeCoercionException(
					String.Format("Error converting {0} to {1}", value.GetType().FullName, targetType.FullName), ex);
			}
		}
		internal Object InstantiateObject(Type objectType, out Dictionary<string, MemberInfo> memberMap)
		{
#if NETFX_CORE
            if (objectType.IsInterface() || objectType.IsAbstract() || objectType.IsValueType())
#else
			if (objectType.IsInterface || objectType.IsAbstract || objectType.IsValueType)
#endif
			{
				throw new JsonTypeCoercionException(
					String.Format(TypeCoercionUtility.ErrorCannotInstantiate, objectType.FullName));
			}

#if NETFX_CORE
            ConstructorInfo ctor = objectType.GetParameterlessConstructor();
#else
            ConstructorInfo ctor = objectType.GetConstructor(Type.EmptyTypes);
#endif
			if (ctor == null)
			{
				throw new JsonTypeCoercionException(
					String.Format(TypeCoercionUtility.ErrorDefaultCtor, objectType.FullName));
			}
			Object result;
			try
			{
				// always try-catch Invoke() to expose real exception
				result = ctor.Invoke(null);
			}
			catch (TargetInvocationException ex)
			{
				if (ex.InnerException != null)
				{
					throw new JsonTypeCoercionException(ex.InnerException.Message, ex.InnerException);
				}
				throw new JsonTypeCoercionException("Error instantiating " + objectType.FullName, ex);
			}

			memberMap = GetMemberMap (objectType);
			
			return result;
		}
        public static bool IsNullable(Type t)
        {
            if (t.IsValueType())
                return IsNullableType(t);

            return true;
        }
        public static bool HasDefaultConstructor(Type t, bool nonPublic)
        {
            if (t.IsValueType())
                return true;

            return (GetDefaultConstructor(t, nonPublic) != null);
        }
        internal static object Convert(IBindingMemberInfo member, Type type, object value)
        {
            if (value == null)
            {
                if (type.IsValueType() && !type.IsNullableType())
                    return Activator.CreateInstance(type);
                return null;
            }
            if (type.IsInstanceOfType(value))
                return value;
#if WPF || ANDROID || TOUCH || WINFORMS || WINDOWS_PHONE || SILVERLIGHT
            var converter = GetTypeConverter(type, member.Member);
            if (converter != null && converter.CanConvertFrom(value.GetType()))
                return converter.ConvertFrom(value);
#endif
#if PCL_WINRT
            if (TypeCodeTable.ContainsKey(value.GetType()))
#else
            if (value is IConvertible)
#endif
                return System.Convert.ChangeType(value, type.GetNonNullableType(), CultureInfo.CurrentCulture);
            if (type == typeof(string))
                return value.ToString();
            return value;
        }