private DictionaryJsonSerializer(Type type, bool encrypt, JsonMappings mappings, bool shouldUseAttributeDefinedInInterface) { _encrypt = encrypt; _mappings = mappings; _shouldUseAttributeDefinedInInterface = shouldUseAttributeDefinedInInterface; Type keyType; if (type.IsAssignableToGenericIDictionary()) { var genericArguments = type.GetGenericArguments(); keyType = genericArguments[0]; if (typeof(IDictionary <string, object>).IsAssignableFrom(type)) { _valueSerializer = JsonSerializerFactory.GetSerializer(genericArguments[1], _encrypt, _mappings, shouldUseAttributeDefinedInInterface); _write = GetIDictionaryOfStringToObjectWriteAction(); } else if (type.IsAssignableToGenericIDictionaryOfStringToAnything()) { _valueSerializer = JsonSerializerFactory.GetSerializer(genericArguments[1], _encrypt, _mappings, shouldUseAttributeDefinedInInterface); _write = GetIDictionaryOfStringToAnythingWriteAction(); } else { _keySerializer = JsonSerializerFactory.GetSerializer(genericArguments[0], _encrypt, _mappings, shouldUseAttributeDefinedInInterface); _valueSerializer = JsonSerializerFactory.GetSerializer(genericArguments[1], _encrypt, _mappings, shouldUseAttributeDefinedInInterface); _write = GetIDictionaryOfAnythingToAnythingWriteAction(); } } else { keyType = typeof(object); _keySerializer = JsonSerializerFactory.GetSerializer(typeof(object), _encrypt, _mappings, shouldUseAttributeDefinedInInterface); _valueSerializer = _keySerializer; _write = GetIDictionaryOfAnythingToAnythingWriteAction(); } if (type.IsInterface) { if (type.IsGenericIDictionary()) { type = typeof(Dictionary <,>).MakeGenericType( type.GetGenericArguments()[0], type.GetGenericArguments()[1]); } else if (type == typeof(IDictionary)) { type = typeof(Dictionary <object, object>); } else { throw new NotSupportedException(type.FullName); } } _createDictionary = GetCreateDictionaryFunc(type); _deserializeKey = GetDeserializeKeyFunc(keyType); _addToDictionary = GetAddToDictionaryAction(type); }
private Func <string, IJsonSerializeOperationInfo, string, object> GetDeserializeKeyFunc(Type type) { if (type == typeof(string)) { return((keyString, info, path) => keyString); } var serializer = JsonSerializerFactory.GetSerializer(type, _encrypt, _mappings, _shouldUseAttributeDefinedInInterface); return((keyString, info, path) => { try { using (var stringReader = new StringReader(keyString)) { using (var reader = new JsonReader(stringReader, info)) { return serializer.DeserializeObject(reader, info, path); } } } catch (XSerializerException) { return keyString; } }); }
private Func <string, Tuple <IJsonSerializerInternal, int> > GetGetSerializerAndArgIndexFunc(ParameterInfo[] parameters) { var propertyNameParameter = Expression.Parameter(typeof(string), "propertyName"); var switchCases = new SwitchCase[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { var serializer = JsonSerializerFactory.GetSerializer(parameters[i].ParameterType, _encrypt, _mappings, _shouldUseAttributeDefinedInInterface); var serializerAndArgIndex = Tuple.Create(serializer, i); var matchingProperties = _type.GetProperties().Where(p => p.Name.Equals(parameters[i].Name, StringComparison.OrdinalIgnoreCase)).ToList(); var switchLabel = matchingProperties.Count == 1 ? matchingProperties[0].GetName(_shouldUseAttributeDefinedInInterface) : parameters[i].Name; switchCases[i] = Expression.SwitchCase( Expression.Constant(serializerAndArgIndex), Expression.Constant(switchLabel)); } var defaultCase = Expression.Constant(null, typeof(Tuple <IJsonSerializerInternal, int>)); var switchExpression = Expression.Switch(propertyNameParameter, defaultCase, switchCases); var getSerializerAndArgIndexLambda = Expression.Lambda <Func <string, Tuple <IJsonSerializerInternal, int> > >( switchExpression, propertyNameParameter); var getSerializerAndArgIndex = getSerializerAndArgIndexLambda.Compile(); return(getSerializerAndArgIndex); }
private ListJsonSerializer(Type type, bool encrypt, JsonMappings mappings) { _encrypt = encrypt; if (type.IsAssignableToGenericIEnumerable()) { var itemType = type.GetGenericIEnumerableType().GetGenericArguments()[0]; _itemSerializer = JsonSerializerFactory.GetSerializer(itemType, _encrypt, mappings); } else { _itemSerializer = JsonSerializerFactory.GetSerializer(typeof(object), _encrypt, mappings); } if (type.IsInterface) { if (type.IsGenericIEnumerable()) { var itemType = type.GetGenericArguments()[0]; type = typeof(List <>).MakeGenericType(itemType); } else { type = typeof(List <object>); } } _createList = GetCreateListFunc(type); _addItem = GetAddItemAction(type); }
private ListJsonSerializer(Type type, bool encrypt, JsonMappings mappings, bool shouldUseAttributeDefinedInInterface) { _encrypt = encrypt; if (type.IsAssignableToGenericIEnumerable()) { var itemType = type.GetGenericIEnumerableType().GetGenericArguments()[0]; _itemSerializer = JsonSerializerFactory.GetSerializer(itemType, _encrypt, mappings, shouldUseAttributeDefinedInInterface); } else { _itemSerializer = JsonSerializerFactory.GetSerializer(typeof(object), _encrypt, mappings, shouldUseAttributeDefinedInInterface); } if (type.IsInterface) { if (type.IsGenericIEnumerable()) { var itemType = type.GetGenericArguments()[0]; type = typeof(List <>).MakeGenericType(itemType); } else { type = typeof(List <object>); } } var listType = type; if (type.IsArray) { if (type.GetArrayRank() > 1) { throw new NotSupportedException("Only arrays with a rank of one are supported: " + type + "."); } var itemType = type.GetElementType(); listType = typeof(List <>).MakeGenericType(itemType); } _createList = GetCreateListFunc(listType); _addItem = GetAddItemAction(listType); _transformList = GetTransformListFunc(type, listType); }
public SerializableJsonProperty(PropertyInfo propertyInfo, bool encrypt, JsonMappings mappings) { if (propertyInfo.DeclaringType == null) { throw new ArgumentException("The DeclaringType of the PropertyInfo must not be null.", "propertyInfo"); } _mappings = mappings; _name = propertyInfo.GetName(); var propertyType = propertyInfo.PropertyType; if (_mappings.MappingsByProperty.ContainsKey(propertyInfo)) { propertyType = _mappings.MappingsByProperty[propertyInfo]; } else if (_mappings.MappingsByType.ContainsKey(propertyType)) { propertyType = _mappings.MappingsByType[propertyType]; } else { var mappingAttribute = (JsonMappingAttribute)Attribute.GetCustomAttribute(propertyInfo, typeof(JsonMappingAttribute)); if (mappingAttribute != null) { propertyType = mappingAttribute.Type; } } _serializer = new Lazy <IJsonSerializerInternal>(() => JsonSerializerFactory.GetSerializer(propertyType, encrypt, _mappings)); _getValue = GetGetValueFunc(propertyInfo, propertyInfo.DeclaringType); if (propertyInfo.IsReadWriteProperty()) { _setValue = GetSetValueAction(propertyInfo, propertyInfo.DeclaringType); } else if (propertyInfo.IsJsonSerializableReadOnlyProperty()) { // TODO: Before any of these checks, see if there is a constructor that matches this property. If so, don't do the "addable" deserialization technique. if (typeof(IDictionary).IsAssignableFrom(propertyType)) { _setValue = (instance, value) => { var dictionary = (IDictionary)value; var destinationDictionary = (IDictionary)_getValue(instance); foreach (DictionaryEntry item in dictionary) { destinationDictionary.Add(item.Key, item.Value); } }; } else if (propertyType.IsAssignableToGenericIDictionary()) { var valueParameter = Expression.Parameter(typeof(object), "value"); var enumerableType = propertyType.GetGenericIEnumerableType(); var convertValue = Expression.Convert(valueParameter, enumerableType); var getEnumeratorMethod = enumerableType.GetMethod("GetEnumerator"); var callGetEnumerator = Expression.Call(convertValue, getEnumeratorMethod); var getEnumeratorLambda = Expression.Lambda <Func <object, IEnumerator> >(callGetEnumerator, valueParameter); var getEnumerator = getEnumeratorLambda.Compile(); var itemParameter = Expression.Parameter(typeof(object), "item"); var dictionaryType = propertyType.GetGenericIDictionaryType(); var dictionaryGenericArguments = dictionaryType.GetGenericArguments(); var keyValuePairType = typeof(KeyValuePair <,>).MakeGenericType( dictionaryGenericArguments[0], dictionaryGenericArguments[1]); var convertItem = Expression.Convert(itemParameter, keyValuePairType); var keyPropertyInfo = keyValuePairType.GetProperty("Key"); Expression keyProperty = Expression.Property(convertItem, keyPropertyInfo); if (keyPropertyInfo.PropertyType.IsValueType) // Boxing is required { keyProperty = Expression.Convert(keyProperty, typeof(object)); } var getItemKeyLambda = Expression.Lambda <Func <object, object> >(keyProperty, itemParameter); var getItemKey = getItemKeyLambda.Compile(); var valuePropertyInfo = keyValuePairType.GetProperty("Value"); Expression valueProperty = Expression.Property(convertItem, valuePropertyInfo); if (valuePropertyInfo.PropertyType.IsValueType) // Boxing is required { valueProperty = Expression.Convert(valueProperty, typeof(object)); } var getItemValueLambda = Expression.Lambda <Func <object, object> >(valueProperty, itemParameter); var getItemValue = getItemValueLambda.Compile(); var destinationDictionaryParameter = Expression.Parameter(typeof(object), "destinationDictionary"); var keyParameter = Expression.Parameter(typeof(object), "key"); var convertDestinationDictionary = Expression.Convert(destinationDictionaryParameter, dictionaryType); var convertKey = Expression.Convert(keyParameter, keyPropertyInfo.PropertyType); convertValue = Expression.Convert(valueParameter, valuePropertyInfo.PropertyType); var addMethod = dictionaryType.GetMethod("Add"); var callAddMethod = Expression.Call( convertDestinationDictionary, addMethod, convertKey, convertValue); var addLambda = Expression.Lambda <Action <object, object, object> >( callAddMethod, destinationDictionaryParameter, keyParameter, valueParameter); var add = addLambda.Compile(); _setValue = (instance, value) => { var dictionaryEnumerator = getEnumerator(value); var destinationDictionary = _getValue(instance); while (dictionaryEnumerator.MoveNext()) { add(destinationDictionary, getItemKey(dictionaryEnumerator.Current), getItemValue(dictionaryEnumerator.Current)); } }; } else if (!propertyType.IsArray) { if (typeof(IList).IsAssignableFrom(propertyType)) { _setValue = (instance, value) => { var list = (IList)value; var destinationList = (IList)_getValue(instance); foreach (var item in list) { destinationList.Add(item); } }; } else if (propertyType.IsAssignableToGenericICollection()) { var destinationListParameter = Expression.Parameter(typeof(object), "destinationList"); var itemParameter = Expression.Parameter(typeof(object), "item"); var collectionType = propertyType.GetGenericICollectionType(); var itemType = collectionType.GetGenericArguments()[0]; var convertItemParameter = Expression.Convert(itemParameter, itemType); var convertDestinationList = Expression.Convert(destinationListParameter, collectionType); var addMethod = collectionType.GetMethod("Add"); var callAddMethod = Expression.Call( convertDestinationList, addMethod, new Expression[] { convertItemParameter }); var lambda = Expression.Lambda <Action <object, object> >( callAddMethod, destinationListParameter, itemParameter); var add = lambda.Compile(); _setValue = (instance, value) => { var destinationList = _getValue(instance); foreach (var item in (IEnumerable)value) { add(destinationList, item); } }; } } } }