private static Expression DeserializeExpression(Expression endpoint, Expression value, Type targetType) { if (targetType == typeof(void)) { return(Expression.Block(typeof(void), value)); } if (targetType == typeof(string)) { return(value); } if (targetType.IsPrimitive) { return(Expression.Call( null, typeof(Convert).GetMethod("To" + targetType.Name, BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string), typeof(IFormatProvider) }, null), value, Expression.Property(null, typeof(CultureInfo).GetProperty("InvariantCulture")))); } if (targetType.IsEnum) { return(Expression.Convert( Expression.Call( typeof(Enum).GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Type), typeof(string), typeof(bool) }, null), Expression.Constant(targetType), value, Expression.Constant(true)), targetType)); } var itemType = targetType.TryGetCollectionItemType(); if (itemType != null) { var enumerable = Expression.Call(typeof(Serializer <>).MakeGenericType(itemType).GetMethod("DeserializeCollection", BindingFlags.NonPublic | BindingFlags.Static), endpoint, value); if (targetType.IsArray) { return(Expression.Call(typeof(Serializer <>).MakeGenericType(itemType).GetMethod("CollectionToArray", BindingFlags.NonPublic | BindingFlags.Static), enumerable)); } return(enumerable); } var nullableType = Nullable.GetUnderlyingType(targetType); if (nullableType != null && Check(nullableType).CanSerialize()) { return(Expression.Condition( Expression.Call(typeof(string).GetMethod("IsNullOrEmpty"), value), Expression.New(targetType), Expression.New(targetType.GetConstructor(new[] { nullableType }), DeserializeExpression(endpoint, value, nullableType)))); } if (Check(targetType).CanBuildProxy()) { MethodInfo customFactory; TryGetCustomProxyFactory(targetType, out customFactory); Expression createExpression; if (customFactory != null) { var realProxyType = ProxyBuilder.BuildProxyType(customFactory.GetParameters()[0].ParameterType); createExpression = Expression.Call( customFactory, Expression.New(realProxyType.GetConstructor(new [] { typeof(IEndpoint), typeof(string) }), endpoint, value)); } else { var type = ProxyBuilder.BuildProxyType(targetType); createExpression = Expression.New(type.GetConstructor(new[] { typeof(IEndpoint), typeof(string) }), endpoint, value); } return(Expression.Condition( Expression.Call( typeof(string).GetMethod("IsNullOrEmpty"), value), Expression.Constant(null, targetType), Expression.Convert(createExpression, targetType))); } if (targetType.IsClass) { if (targetType.IsDefined(typeof(DataContractAttribute), true)) { return(Expression.Call(typeof(Serializer <T>).GetMethod("DeserializeClass", BindingFlags.NonPublic | BindingFlags.Static), value)); } return(Expression.Block( Expression.Throw(Expression.New(typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }), Expression.Constant("cannot deserialize non-data class"))), Expression.Default(targetType))); } throw new Exception("cannot deserialize expression to type " + targetType); }