public static TypeAccessor Create(ITypeSerializer serializer, TypeConfig typeConfig, FieldInfo fieldInfo) { return(new TypeAccessor { PropertyType = fieldInfo.FieldType, GetProperty = serializer.GetParseFn(fieldInfo.FieldType), SetProperty = GetSetFieldMethod(typeConfig, fieldInfo), }); }
private static SetPropertyDelegate GetSetFieldMethod(TypeConfig typeConfig, FieldInfo fieldInfo) { if (fieldInfo.ReflectedType() != fieldInfo.DeclaringType) { fieldInfo = fieldInfo.DeclaringType.GetFieldInfo(fieldInfo.Name); } return(PclExport.Instance.GetSetFieldMethod(fieldInfo)); }
public static TypeAccessor Create(ITypeSerializer serializer, TypeConfig typeConfig, PropertyInfo propertyInfo) { return(new TypeAccessor { PropertyType = propertyInfo.PropertyType, GetProperty = serializer.GetParseFn(propertyInfo.PropertyType), SetProperty = GetSetPropertyMethod(typeConfig, propertyInfo), }); }
internal static Dictionary <string, TypeAccessor> GetTypeAccessorMap(TypeConfig typeConfig, ITypeSerializer serializer) { var type = typeConfig.Type; var isDataContract = type.IsDto(); var propertyInfos = type.GetSerializableProperties(); var fieldInfos = type.GetSerializableFields(); if (propertyInfos.Length == 0 && fieldInfos.Length == 0) { return(null); } var map = new Dictionary <string, TypeAccessor>(StringComparer.OrdinalIgnoreCase); if (propertyInfos.Length != 0) { foreach (var propertyInfo in propertyInfos) { var propertyName = propertyInfo.Name; if (isDataContract) { var dcsDataMember = propertyInfo.GetDataMember(); if (dcsDataMember != null && dcsDataMember.Name != null) { propertyName = dcsDataMember.Name; } } map[propertyName] = TypeAccessor.Create(serializer, typeConfig, propertyInfo); } } if (fieldInfos.Length != 0) { foreach (var fieldInfo in fieldInfos) { var field = fieldInfo.Name; if (isDataContract) { var dcsDataMember = fieldInfo.GetDataMember(); if (dcsDataMember != null && dcsDataMember.Name != null) { field = dcsDataMember.Name; } } map[field] = TypeAccessor.Create(serializer, typeConfig, fieldInfo); } } return(map); }
internal static ParseStringDelegate GetParseMethod(TypeConfig typeConfig) { var type = typeConfig.Type; if (!type.IsStandardClass()) { return(null); } var map = DeserializeTypeRef.GetTypeAccessorMap(typeConfig, Serializer); var ctorFn = JsConfig.ModelFactory(type); if (map == null) { return(value => ctorFn()); } return(typeof(TSerializer) == typeof(JsonTypeSerializer) ? (ParseStringDelegate)(value => DeserializeTypeRefJson.StringToType(typeConfig, value, ctorFn, map)) : value => DeserializeTypeRefJsv.StringToType(typeConfig, value, ctorFn, map)); }
private static SetPropertyDelegate GetSetPropertyMethod(TypeConfig typeConfig, PropertyInfo propertyInfo) { if (propertyInfo.ReflectedType() != propertyInfo.DeclaringType) { propertyInfo = propertyInfo.DeclaringType.GetPropertyInfo(propertyInfo.Name); } if (!propertyInfo.CanWrite && !typeConfig.EnableAnonymousFieldSetterses) { return(null); } FieldInfo fieldInfo = null; if (!propertyInfo.CanWrite) { //TODO: What string comparison is used in SST? string fieldNameFormat = Env.IsMono ? "<{0}>" : "<{0}>i__Field"; var fieldName = string.Format(fieldNameFormat, propertyInfo.Name); var fieldInfos = typeConfig.Type.GetWritableFields(); foreach (var f in fieldInfos) { if (f.IsInitOnly && f.FieldType == propertyInfo.PropertyType && f.Name == fieldName) { fieldInfo = f; break; } } if (fieldInfo == null) { return(null); } } return(PclExport.Instance.GetSetMethod(propertyInfo, fieldInfo)); }
private ParseStringDelegate GetCoreParseFn <T>() { var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); if (JsConfig <T> .HasDeserializeFn) { return(value => JsConfig <T> .ParseFn(Serializer, value)); } if (type.IsEnum()) { return(x => ParseUtils.TryParseEnum(type, Serializer.UnescapeSafeString(x))); } if (type == typeof(string)) { return(Serializer.UnescapeString); } if (type == typeof(object)) { return(DeserializeType <TSerializer> .ObjectStringToType); } var specialParseFn = ParseUtils.GetSpecialParseMethod(type); if (specialParseFn != null) { return(specialParseFn); } if (type.IsArray) { return(DeserializeArray <T, TSerializer> .Parse); } var builtInMethod = DeserializeBuiltin <T> .Parse; if (builtInMethod != null) { return(value => builtInMethod(Serializer.UnescapeSafeString(value))); } if (type.HasGenericType()) { if (type.IsOrHasGenericInterfaceTypeOf(typeof(IList <>))) { return(DeserializeList <T, TSerializer> .Parse); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IDictionary <,>))) { return(DeserializeDictionary <TSerializer> .GetParseMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(ICollection <>))) { return(DeserializeCollection <TSerializer> .GetParseMethod(type)); } if (type.HasAnyTypeDefinitionsOf(typeof(Queue <>)) || type.HasAnyTypeDefinitionsOf(typeof(Stack <>))) { return(DeserializeSpecializedCollections <T, TSerializer> .Parse); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(KeyValuePair <,>))) { return(DeserializeKeyValuePair <TSerializer> .GetParseMethod(type)); } if (type.IsOrHasGenericInterfaceTypeOf(typeof(IEnumerable <>))) { return(DeserializeEnumerable <T, TSerializer> .Parse); } var customFn = DeserializeCustomGenericType <TSerializer> .GetParseMethod(type); if (customFn != null) { return(customFn); } } var pclParseFn = PclExport.Instance.GetJsReaderParseMethod <TSerializer>(typeof(T)); if (pclParseFn != null) { return(pclParseFn); } var isDictionary = typeof(T) != typeof(IEnumerable) && typeof(T) != typeof(ICollection) && (typeof(T).AssignableFrom(typeof(IDictionary)) || typeof(T).HasInterface(typeof(IDictionary))); if (isDictionary) { return(DeserializeDictionary <TSerializer> .GetParseMethod(type)); } var isEnumerable = typeof(T).AssignableFrom(typeof(IEnumerable)) || typeof(T).HasInterface(typeof(IEnumerable)); if (isEnumerable) { var parseFn = DeserializeSpecializedCollections <T, TSerializer> .Parse; if (parseFn != null) { return(parseFn); } } if (type.IsValueType()) { var staticParseMethod = StaticParseMethod <T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value))); } } else { var staticParseMethod = StaticParseRefTypeMethod <TSerializer, T> .Parse; if (staticParseMethod != null) { return(value => staticParseMethod(Serializer.UnescapeSafeString(value))); } } var typeConstructor = DeserializeType <TSerializer> .GetParseMethod(TypeConfig <T> .GetState()); if (typeConstructor != null) { return(typeConstructor); } var stringConstructor = DeserializeTypeUtils.GetParseMethod(type); if (stringConstructor != null) { return(stringConstructor); } return(DeserializeType <TSerializer> .ParseAbstractType <T>); }
internal static object StringToType( TypeConfig typeConfig, string strType, EmptyCtorDelegate ctorFn, Dictionary <string, TypeAccessor> typeAccessorMap) { var index = 0; var type = typeConfig.Type; if (strType == null) { return(null); } //if (!Serializer.EatMapStartChar(strType, ref index)) for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline if (strType[index++] != JsWriter.MapStartChar) { throw DeserializeTypeRef.CreateSerializationError(type, strType); } if (JsonTypeSerializer.IsEmptyMap(strType, index)) { return(ctorFn()); } object instance = null; var propertyResolver = JsConfig.PropertyConvention == PropertyConvention.Lenient ? ParseUtils.LenientPropertyNameResolver : ParseUtils.DefaultPropertyNameResolver; var strTypeLength = strType.Length; while (index < strTypeLength) { var propertyName = JsonTypeSerializer.ParseJsonString(strType, ref index); //Serializer.EatMapKeySeperator(strType, ref index); for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline if (strType.Length != index) { index++; } var propertyValueStr = Serializer.EatValue(strType, ref index); var possibleTypeInfo = propertyValueStr != null && propertyValueStr.Length > 1; //if we already have an instance don't check type info, because then we will have a half deserialized object //we could throw here or just use the existing instance. if (instance == null && possibleTypeInfo && propertyName == JsWriter.TypeAttr) { var explicitTypeName = Serializer.ParseString(propertyValueStr); var explicitType = JsConfig.TypeFinder(explicitTypeName); if (explicitType != null && !explicitType.IsInterface() && !explicitType.IsAbstract()) { instance = explicitType.CreateInstance(); } if (instance == null) { Tracer.Instance.WriteWarning("Could not find type: " + propertyValueStr); } else { //If __type info doesn't match, ignore it. if (!type.InstanceOfType(instance)) { instance = null; } else { var derivedType = instance.GetType(); if (derivedType != type) { var derivedTypeConfig = new TypeConfig(derivedType); var map = DeserializeTypeRef.GetTypeAccessorMap(derivedTypeConfig, Serializer); if (map != null) { typeAccessorMap = map; } } } } Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); continue; } if (instance == null) { instance = ctorFn(); } var typeAccessor = propertyResolver.GetTypeAccessorForProperty(propertyName, typeAccessorMap); var propType = possibleTypeInfo && propertyValueStr[0] == '_' ? TypeAccessor.ExtractType(Serializer, propertyValueStr) : null; if (propType != null) { try { if (typeAccessor != null) { //var parseFn = Serializer.GetParseFn(propType); var parseFn = JsonReader.GetParseFn(propType); var propertyValue = parseFn(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline if (index != strType.Length) { var success = strType[index] == JsWriter.ItemSeperator || strType[index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline } } continue; } catch (Exception e) { if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException(propertyName, propertyValueStr, propType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr); } } } if (typeAccessor != null && typeAccessor.GetProperty != null && typeAccessor.SetProperty != null) { try { var propertyValue = typeAccessor.GetProperty(propertyValueStr); if (typeConfig.OnDeserializing != null) { propertyValue = typeConfig.OnDeserializing(instance, propertyName, propertyValue); } typeAccessor.SetProperty(instance, propertyValue); } catch (Exception e) { if (JsConfig.ThrowOnDeserializationError) { throw DeserializeTypeRef.GetSerializationException(propertyName, propertyValueStr, typeAccessor.PropertyType, e); } else { Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr); } } } else if (typeConfig.OnDeserializing != null) { // the property is not known by the DTO typeConfig.OnDeserializing(instance, propertyName, propertyValueStr); } //Serializer.EatItemSeperatorOrMapEndChar(strType, ref index); for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline if (index != strType.Length) { var success = strType[index] == JsWriter.ItemSeperator || strType[index] == JsWriter.MapEndChar; index++; if (success) { for (; index < strType.Length; index++) { var c = strType[index]; if (c >= JsonTypeSerializer.WhiteSpaceFlags.Length || !JsonTypeSerializer.WhiteSpaceFlags[c]) { break; } } //Whitespace inline } } } return(instance); }