예제 #1
0
        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);
        }
예제 #2
0
        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;
                }
            });
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                            }
                        };
                    }
                }
            }
        }