Example #1
0
        /// <summary>
        /// Deserializes the specified json string.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <param name="currentReadIndex">Index of the current read.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public override object Deserialize(string json, ref int currentReadIndex, SerializationContext context)
        {
            // check if value is null
            int expectedSepIndex = currentReadIndex + keyLength;

            if (json[expectedSepIndex] == 'n' &&
                json[expectedSepIndex + 1] == 'u' &&
                json[expectedSepIndex + 2] == 'l' &&
                json[expectedSepIndex + 3] == 'l')
            {
                currentReadIndex = expectedSepIndex + 4;
                return(null);
            }

            if (json[expectedSepIndex + 1] == Structure.CharQuotationMark &&
                json[expectedSepIndex + 2] == '#' &&
                json[expectedSepIndex + 3] == 't' &&
                json[expectedSepIndex + 4] == 'y' &&
                json[expectedSepIndex + 5] == 'p' &&
                json[expectedSepIndex + 6] == 'e'
                )
            {
                return(DeserializeSpecialType(json, ref currentReadIndex, context, expectedSepIndex));
            }


            if (isObject)
            {
                Type objectTargetType = null;
                if (unknownTypeResolver != null)
                {
                    context.Key             = this.key;
                    context.ValueStartIndex = currentReadIndex;
                    context.ArrayIndex      = null;
                    context.JsonString      = json;
                    if (type.IsInterface)
                    {
                        context.InterfaceType = this.type;
                    }

                    objectTargetType = unknownTypeResolver(context);

                    if (context.InterfaceType != null)
                    {
                        context.InterfaceType = null;
                    }
                }

                if (objectTargetType == null)
                {
                    objectTargetType = Structure.GetDefaultType(json, expectedSepIndex);

                    if (objectTargetType == null)
                    {
                        throw new InvalidOperationException("Can't determine target type for JSON key: \"" + context.Key + "\"");
                    }
                }

                IJsonTypeStructure currentObjectStructure;
                if (!typeSerializerCache.TryGetValue(objectTargetType, out currentObjectStructure))
                {
                    currentObjectStructure = Structure.DetermineStructure(objectTargetType, this.key, context, this.isArrayItem);
                    typeSerializerCache[objectTargetType] = currentObjectStructure;
                }

                return(currentObjectStructure.Deserialize(json, ref currentReadIndex, context));
            }
            else
            {
                if (json[currentReadIndex] != Structure.CharLeftBrace &&
                    !isArrayItem)
                {
                    if (json[currentReadIndex] == Structure.CharComma)
                    {
                        currentReadIndex += 1;
                    }

                    expectedSepIndex = currentReadIndex + keyLength - 1;

                    if (json[expectedSepIndex] == Structure.CharColon)
                    {
                        currentReadIndex = expectedSepIndex + 1;
                    }
                    else
                    {
                        throw new Exception("Unexpected JSON data!");
                    }
                }

                if (this.concreteTargetType == null)
                {
                    // try get static target type
                    if (type.IsInterface || type.IsAbstract)
                    {
                        context.InterfaceType = type;
                        context.Key           = key;

                        Type itemTypeResolved = unknownTypeResolver(context);
                        if (itemTypeResolved != null)
                        {
                            concreteTargetType = itemTypeResolved;
                        }
                        context.InterfaceType = null;
                    }
                    else
                    {
                        concreteTargetType = type;
                    }
                }

                // create target object
                object target;
                try
                {
                    target = TypeService.CreateInstance(this.concreteTargetType);
                }
                catch (Exception ex)
                {
                    throw new Exception("Can't create object instance for \"" + this.concreteTargetType + "\" - \"" + type + "\"!", ex);
                }
                object oldParentObj = context.ParentObject;
                context.ParentObject = target;

                // jump over opening brace
                currentReadIndex += 1;

                for (int propIndex = 0; propIndex < objectStructure.Length; propIndex++)
                {
                    IJsonTypeStructure structure = objectStructure[propIndex];
                    var setPropertyAccessor      = setAccessorByPropertyIndex[propIndex];

                    // check out of order json
                    int expectedKeyStartIndex = currentReadIndex + 1;
                    int actualKeyIndex        = json.IndexOf(structure.Key, expectedKeyStartIndex);
                    if (actualKeyIndex != expectedKeyStartIndex ||
                        json[structure.Key.Length + actualKeyIndex] != Structure.CharQuotationMark)     // Recognize key with the same begin string but different ending
                    {
                        // out of order key recognized


                        int keyEndIndex       = json.IndexOf(Structure.CharQuotationMark, expectedKeyStartIndex);
                        int?keyStructureIndex = null;
                        StructureComplexOutOfOrder cachedOutOfOrderStruct = null;
                        string actualKey = null;
                        if (keyEndIndex != -1)  // ignore if end of json is reached
                        {
                            actualKey = json.Substring(expectedKeyStartIndex, keyEndIndex - expectedKeyStartIndex);

                            // check if out of order structure is already cached
                            if (outOfOrderStructures != null)
                            {
                                for (int indexCachedOutOfOrder = 0; indexCachedOutOfOrder < outOfOrderStructures.Count; indexCachedOutOfOrder++)
                                {
                                    var cachedItem = outOfOrderStructures[indexCachedOutOfOrder];

                                    if (cachedItem.ObjectStructure[propIndex].Key == actualKey)
                                    {
                                        cachedOutOfOrderStruct = cachedItem;
                                        break;
                                    }
                                }
                            }

                            if (cachedOutOfOrderStruct == null)
                            {
                                // find out of order key
                                keyStructureIndex = FindOutOfOrderKey(objectStructure, actualKey);
                            }
                        }

                        if (cachedOutOfOrderStruct != null)
                        {
                            structure           = cachedOutOfOrderStruct.ObjectStructure[propIndex];
                            setPropertyAccessor = cachedOutOfOrderStruct.SetAccessorByPropertyIndex[propIndex];
                        }
                        else if (keyStructureIndex.HasValue)
                        {
                            lock (syncObj)
                            {
                                // create or move out of order structure

                                if (outOfOrderStructures == null)
                                {
                                    outOfOrderStructures = new List <StructureComplexOutOfOrder>();
                                }

                                // try reuse existing out of order array
                                StructureComplexOutOfOrder currentOutOfOrderStruct;
                                var existing = outOfOrderStructures.Where(ooo => ooo.MaxTargetIndex < propIndex).FirstOrDefault();

                                IJsonTypeStructure[]      sourceStructure = objectStructure;
                                Func <object, object>[]   sourceGetAccessorByPropertyIndex = getAccessorByPropertyIndex;
                                Action <object, object>[] sourceSetAccessorByPropertyIndex = setAccessorByPropertyIndex;

                                // create new cloned out of order strucutre
                                if (existing == null)
                                {
                                    currentOutOfOrderStruct = new StructureComplexOutOfOrder()
                                    {
                                        ObjectStructure            = (IJsonTypeStructure[])sourceStructure.Clone(),
                                        GetAccessorByPropertyIndex = (Func <object, object>[])sourceGetAccessorByPropertyIndex.Clone(),
                                        SetAccessorByPropertyIndex = (Action <object, object>[])sourceSetAccessorByPropertyIndex.Clone()
                                    };
                                }
                                else
                                {
                                    currentOutOfOrderStruct = existing;
                                    sourceStructure         = existing.ObjectStructure;
                                    structure = sourceStructure[propIndex];
                                    sourceGetAccessorByPropertyIndex = existing.GetAccessorByPropertyIndex;
                                    sourceSetAccessorByPropertyIndex = existing.SetAccessorByPropertyIndex;

                                    // search in chached object structure again
                                    keyStructureIndex = FindOutOfOrderKey(sourceStructure, actualKey);
                                }

                                // switch object structure to received json order
                                IJsonTypeStructure foundOutOfOrderStructure = sourceStructure[keyStructureIndex.Value];
                                currentOutOfOrderStruct.ObjectStructure[propIndex] = foundOutOfOrderStructure;
                                currentOutOfOrderStruct.ObjectStructure[keyStructureIndex.Value] = structure;
                                structure = foundOutOfOrderStructure;
                                currentOutOfOrderStruct.MaxTargetIndex = propIndex;

                                // switch value setter
                                var currentAccessor         = sourceGetAccessorByPropertyIndex[propIndex];
                                var foundOutOfOrderAccessor = sourceGetAccessorByPropertyIndex[keyStructureIndex.Value];
                                currentOutOfOrderStruct.GetAccessorByPropertyIndex[propIndex] = foundOutOfOrderAccessor;
                                currentOutOfOrderStruct.GetAccessorByPropertyIndex[keyStructureIndex.Value] = currentAccessor;

                                var currentAccessorSet         = sourceSetAccessorByPropertyIndex[propIndex];
                                var foundOutOfOrderAccessorSet = sourceSetAccessorByPropertyIndex[keyStructureIndex.Value];
                                currentOutOfOrderStruct.SetAccessorByPropertyIndex[propIndex] = foundOutOfOrderAccessorSet;
                                currentOutOfOrderStruct.SetAccessorByPropertyIndex[keyStructureIndex.Value] = currentAccessorSet;

                                setPropertyAccessor = foundOutOfOrderAccessorSet;

                                if (existing == null)
                                {
                                    outOfOrderStructures.Add(currentOutOfOrderStruct);
                                }
                            }
                        }
                        else
                        {
                            if (context.Serializer.IsMissingFieldDataAllowed)
                            {
                                if (SkipJsonElement(json, ref currentReadIndex))
                                {
                                    propIndex--; // re-read current structure
                                }
                                continue;        // ignore missing field
                            }
                            else
                            {
                                throw new KeyNotFoundException(string.Format("The key: \"{0}\" is not present in the object structure! JSON: \"{1}\"; Target Type: \"{2}\"", actualKey, json, this.type.AssemblyQualifiedName));
                            }
                        }
                    }

                    object value = structure.Deserialize(json, ref currentReadIndex, context);

                    if (value != null)
                    {
                        setPropertyAccessor(target, value);
                    }

                    if (json[currentReadIndex] == Structure.CharRightBrace)
                    {
                        // end reached
                        currentReadIndex++;
                        break;
                    }

                    currentReadIndex++;
                }

                if (json[currentReadIndex - 1] != Structure.CharRightBrace)
                {
                    if (context.Serializer.IsMissingFieldDataAllowed)
                    {
                        // json object contains more data than expected from the type structure
                        // skip futher object data
                        SkipJsonObject(json, ref currentReadIndex);
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("The json object contains more data than expected in target type! JSON: \"{0}\"; Key: \"{1}\"; Target Type: \"{2}\"", json, this.key, this.type.AssemblyQualifiedName));
                    }
                }

                context.ParentObject = oldParentObj;

                return(target);
            }
        }
Example #2
0
        public bool TryGetExport(Type type, Type injectTargetType, List <Type> pendingCreateList, out object instance)
        {
            if (discoveryConditionItems != null)
            {
                DiscoveryContext ctx = new DiscoveryContext(type, injectTargetType);

                foreach (var cond in discoveryConditionItems)
                {
                    if (cond.IsMatching(ctx))
                    {
                        return(cond.TargetContainer.TryGetExport(type, injectTargetType, out instance));
                    }
                }
            }

            if (localShare.SharedLocalInstances.TryGetValue(type, out instance))
            {
                return(true);
            }

            if (hostSessionsSharedInstances.TryGetValue(type, out instance))
            {
                return(true);
            }

            Type targetType;
            var  contract = currentContract;

            if (type.IsInterface)
            {
                if (contract != null)
                {
                    if (contract.TryGetSessionInstance(type, out instance))
                    {
                        return(true);
                    }
                }

                if (!localShare.TryFindInterfaceImplementation(type, injectTargetType, out targetType))
                {
                    // not found > check if multiple import
                    if (type.GetInterface(typeof(System.Collections.IEnumerable).FullName) != null)
                    {
                        var multiImportColl = localShare.CollectLocalMultiImports(this, type, injectTargetType, pendingCreateList);
                        if (multiImportColl != null)
                        {
                            instance = multiImportColl;
                            return(true);
                        }
                    }
                    else
                    {
                        instance = null;
                        return(false);
                    }
                }
            }
            else if (type.IsArray)
            {
                var multiImportColl = this.localShare.CollectLocalMultiImports(this, type, injectTargetType, pendingCreateList);
                if (multiImportColl != null)
                {
                    instance = multiImportColl;
                    return(true);
                }
                else
                {
                    instance = null;
                    return(false);
                }
            }
            else
            {
                targetType = type;
            }

            object[]        outParams;
            ParameterInfo[] outParamsInfo;
            instance = TypeService.CreateInstance(targetType, DetermineConstructorImportInstance, pendingCreateList, out outParams, out outParamsInfo);
            localShare.CheckOutParamsSubscriptions(instance, outParams, this, type);

            localShare.RegisterSharedConstructorInstances(type, instance, outParams, outParamsInfo);

            if (contract != null &&
                this.localSessionServiceInterfaceTypesResolved.Contains(type))
            {
                // update contract service cache here as well to be not dependent on the registration order in nested cases
                int cachedAtIndex = Array.IndexOf <Type>(this.localSessionServiceInterfaceTypesResolved, type);
                contract.LocalServices[cachedAtIndex] = instance;
            }

            //todo: parent container handling

            return(true);
        }
Example #3
0
        internal IEnumerable CollectLocalMultiImports(TalkCompositionHost host, Type type, Type injectTargetType, List <Type> pendingCreateList)
        {
            // multiple imports
            // 1. determine generic target interface type
            // 2. create concreate target collection instance
            // 3. add one instance of all local implementations
            Type genericCollectionInterface = type.GetInterface("IEnumerable`1");

            if (type.IsGenericType ||
                genericCollectionInterface != null)
            {
                Type   enumerableClassType = null;
                Type[] genericTypes        = type.GetGenericArguments();
                if (genericTypes.Length == 1)
                {
                    Type listType = typeof(List <>);
                    enumerableClassType = listType.MakeGenericType(genericTypes);
                }
                else if (genericTypes.Length == 0 &&
                         genericCollectionInterface != null)
                {
                    genericTypes = genericCollectionInterface.GetGenericArguments();
                    Type listType = typeof(List <>);
                    enumerableClassType = listType.MakeGenericType(genericTypes);
                }

                if (enumerableClassType != null && genericTypes.Length == 1)
                {
                    Type targetInterfaceType = genericTypes[0];

                    bool  isShared         = IsMultiShared(targetInterfaceType);
                    IList targetCollection = null;
                    if (isShared)
                    {
                        targetCollection = GetLocalSharedMultipleInstances(targetInterfaceType);
                    }

                    if (targetCollection == null)
                    {
                        targetCollection = (IList)TypeService.CreateInstance(enumerableClassType);

                        // create new instances
                        HashSet <Type> createdTypes = new HashSet <Type>();
                        foreach (Type implType in this.FindInterfaceImplementations(targetInterfaceType, injectTargetType))
                        {
                            if (!createdTypes.Contains(implType) && injectTargetType != implType)
                            {
                                object[]        outParams;
                                ParameterInfo[] outParamsInfo;
                                object          itemInstance;
                                if (host != null)
                                {
                                    itemInstance = TypeService.CreateInstance(implType, host.DetermineConstructorImportInstance, pendingCreateList, out outParams, out outParamsInfo);
                                }
                                else
                                {
                                    itemInstance = TypeService.CreateInstance(implType, this.DetermineConstructorImportInstance, pendingCreateList, out outParams, out outParamsInfo);
                                }

                                CheckOutParamsSubscriptions(itemInstance, outParams, host, targetInterfaceType);
                                targetCollection.Add(itemInstance);

                                RegisterSharedConstructorInstances(targetInterfaceType, itemInstance, outParams, outParamsInfo);

                                createdTypes.Add(implType);
                            }
                        }

                        if (isShared)
                        {
                            if (localSharedMultipleInterfaceInstances == null)
                            {
                                localSharedMultipleInterfaceInstances = new Dictionary <Type, IList>();
                            }

                            // add to shared dictionary
                            localSharedMultipleInterfaceInstances.Add(targetInterfaceType, targetCollection);
                        }
                    }

                    if (type.IsArray)
                    {
                        Type arrayItemType = type.GetElementType();

                        Array targetArray = Array.CreateInstance(arrayItemType, targetCollection.Count);
                        for (int i = 0; i < targetCollection.Count; i++)
                        {
                            targetArray.SetValue(targetCollection[i], i);
                        }

                        return(targetArray);
                    }
                    else
                    {
                        return(targetCollection);
                    }
                }
            }

            return(null);
        }
Example #4
0
        public bool TryGetExport(Type type, Type injectTargetType, List <Type> pendingCreateList, out object instance)
        {
            if (discoveryConditionItems != null)
            {
                DiscoveryContext ctx = new DiscoveryContext(type, injectTargetType);

                foreach (var cond in discoveryConditionItems)
                {
                    if (cond.IsMatching(ctx))
                    {
                        return(cond.TargetContainer.TryGetExport(type, injectTargetType, out instance));
                    }
                }
            }

            if (this.SharedLocalInstances.TryGetValue(type, out instance))
            {
                return(true);
            }

            //if (hostSessionsSharedInstances.TryGetValue(type, out instance))
            //{
            //    return true;
            //}

            if (ParentContainer != null &&
                ParentContainer is IContainerSharedByType parentShared &&
                parentShared.TryGetCachedLocalExport(type, out instance))
            {
                return(true);
            }

            // create new instance
            Type targetType;

            if (type.IsInterface)
            {
                //var contract = currentContract;
                //if (contract != null)
                //{
                //    if (contract.TryGetSessionInstance(type, out instance))
                //    {
                //        return true;
                //    }
                //}

                if (!TryFindInterfaceImplementation(type, injectTargetType, out targetType))
                {
                    // not found > check if multiple import
                    if (type.GetInterface(typeof(System.Collections.IEnumerable).FullName) != null)
                    {
                        var multiImportColl = this.CollectLocalMultiImports(null, type, injectTargetType, pendingCreateList);
                        if (multiImportColl != null)
                        {
                            instance = multiImportColl;
                            return(true);
                        }
                        // todo: else?
                    }
                    else
                    {
                        instance = null;
                        return(false);
                    }
                }
            }
            else if (type.IsArray)
            {
                var multiImportColl = this.CollectLocalMultiImports(null, type, injectTargetType, pendingCreateList);
                if (multiImportColl != null)
                {
                    instance = multiImportColl;
                    return(true);
                }
                else
                {
                    instance = null;
                    return(false);
                }
            }
            else
            {
                targetType = type;
            }

            object[]        outParams;
            ParameterInfo[] outParamsInfo;
            instance = TypeService.CreateInstance(targetType, DetermineConstructorImportInstance, pendingCreateList, out outParams, out outParamsInfo);
            this.CheckOutParamsSubscriptions(instance, outParams, null, type);

            this.RegisterSharedConstructorInstances(type, instance, outParams, outParamsInfo);

            return(true);
        }
Example #5
0
        public object ReadValue(IStreamReader reader, ISerializeContext context, bool isReadTypeIdExpected)
        {
            context.Key        = this.Name;
            context.ArrayIndex = null;

            if (isReadTypeIdExpected)
            {
                // read type of property
                uint actualTypeId = reader.ReadUInt32();

                if (TypeId != actualTypeId)
                {
                    if (actualTypeId == (int)ItemType.ComplexObject)
                    {
                        // Special read > only null expected
                        byte contentObjType = reader.ReadUInt8();

                        if (contentObjType == ValueItem.NullValueIdent)
                        {
                            return(null);
                        }
                        else
                        {
                            throw new ArgumentException("ComplexObject type ID is only expected with null!");
                        }
                    }

                    var actualStructure = context.GetByTypeId(actualTypeId);

                    if (actualStructure == null)
                    {
                        // type not in local cache > type meta info exptected
                        actualStructure = TypeMetaStructure.ReadContentTypeMetaInfo(reader, actualTypeId, context);
                    }

                    if (actualStructure.IsTypePrefixExpected)
                    {
                        if (actualStructure is ITypePrefix)
                        {
                            // type id already consumed > do not read again
                            return(((ITypePrefix)actualStructure).ReadValue(reader, context, false));
                        }
                        else
                        {
                            return(actualStructure.ReadValue(reader, context));
                        }
                    }
                    else
                    {
                        // read content type because of unknown strucutre
                        byte contentObjType = reader.ReadUInt8();

                        if (contentObjType == ValueItem.NullValueIdent)
                        {
                            return(null);
                        }
                        else
                        {
                            return(actualStructure.ReadValue(reader, context));
                        }
                    }
                }
            }


            byte contentType = reader.ReadUInt8();

            if (contentType == ValueItem.TypeMetaInfo)
            {
                // type meta data already loaded for type id > skip data
                TypeMetaStructure.SkipTypeMetaInfo(reader);
                contentType = reader.ReadUInt8();
            }

            switch (contentType)
            {
            case ValueItem.SingleObjectIdent:
                object newObject = TypeService.CreateInstance(concreteTargetType);

                object oldParentObj = context.ParentObject;
                context.ParentObject = newObject;

                for (int itemIndex = 0; itemIndex < items.Count; itemIndex++)
                {
                    var item = items[itemIndex];

                    var itemValue = item.ReadValue(reader, context);
                    item.SetItemValue(newObject, itemValue);
                }

                context.ParentObject = oldParentObj;

                return(newObject);

            case ValueItem.NullValueIdent:
                return(null);

            case ValueItem.CollectionObjectIdent:
                throw new NotImplementedException();

            default:
                throw new InvalidOperationException($"Type ident {contentType} not expected!");
            }
        }
Example #6
0
        /// <summary>
        /// Deserializes the specified json string.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <param name="currentReadIndex">Index of the current read.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public override object Deserialize(string json, ref int currentReadIndex, SerializationContext context)
        {
            currentReadIndex = currentReadIndex + keyLength;

            if (json[currentReadIndex] == Structure.CharLeftSquareBrace)
            {
                currentReadIndex++;

                if (type.IsArray)
                {
                    ArrayList soureList = new ArrayList();
                    while (true)
                    {
                        if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                        {
                            // is empty array
                            currentReadIndex += 1;
                            break;
                        }

                        object itemValue = DeserializeArrayItem(json, ref currentReadIndex, soureList.Count, context);

                        soureList.Add(itemValue);

                        if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                        {
                            currentReadIndex += 1;
                            break;
                        }

                        currentReadIndex += 1;
                    }

                    // copy items to target array
                    Array targetValueArray = Array.CreateInstance(itemType, soureList.Count);
                    for (int i = 0; i < soureList.Count; i++)
                    {
                        targetValueArray.SetValue(soureList[i], i);
                    }
                    return(targetValueArray);
                }
                else
                {
                    object targetCollectionObj = TypeService.CreateInstance(targetCollectionType);

                    if (targetCollectionObj is IList)
                    {
                        IList targetCollection = (IList)targetCollectionObj;

                        while (true)
                        {
                            if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                            {
                                // is empty array
                                currentReadIndex += 1;
                                break;
                            }

                            object itemValue = DeserializeArrayItem(json, ref currentReadIndex, targetCollection.Count, context);
                            targetCollection.Add(itemValue);

                            if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                            {
                                currentReadIndex += 1;
                                break;
                            }

                            currentReadIndex += 1;
                        }
                        return(targetCollection);
                    }
                    else
                    {
                        // collection does not implement IList
                        // Unable to cast to ICollection<T>
                        // try to get Add method using reflection
                        MethodInfo miAdd;
                        if (specialCollectionTypeAddMethodCache == null ||
                            !specialCollectionTypeAddMethodCache.TryGetValue(targetCollectionType, out miAdd))
                        {
                            miAdd = targetCollectionType.GetMethod("Add");
                            if (miAdd != null)
                            {
                                specialCollectionTypeAddMethodCache = new ConcurrentDictionary <Type, MethodInfo>();
                                specialCollectionTypeAddMethodCache.TryAdd(targetCollectionType, miAdd);
                            }
                            else
                            {
                                throw new InvalidCastException("The collection type " + targetCollectionType.FullName + " is not supported! Unable to get items \"Add\" method.");
                            }
                        }

                        int count = 0;
                        while (true)
                        {
                            if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                            {
                                // is empty array
                                currentReadIndex += 1;
                                break;
                            }

                            object itemValue = DeserializeArrayItem(json, ref currentReadIndex, count, context);
                            miAdd.Invoke(targetCollectionObj, new object[] { itemValue });

                            if (json[currentReadIndex] == Structure.CharRightSquareBracet)
                            {
                                currentReadIndex += 1;
                                break;
                            }

                            currentReadIndex += 1;
                            count++;
                        }
                        return(targetCollectionObj);
                    }
                }
            }
            else if (json[currentReadIndex] == Structure.CharQuotationMark &&
                     isByteArray)
            {
                // Byte array base64 encoding optimization
                currentReadIndex++;
                int endDataIndex = json.IndexOf(Structure.CharQuotationMark, currentReadIndex);

                if (endDataIndex > 0)
                {
                    int    length     = endDataIndex - currentReadIndex;
                    string base64Data = json.Substring(currentReadIndex, length);
                    byte[] data       = Convert.FromBase64String(base64Data);
                    currentReadIndex += length + 1;
                    return(data);
                }
                else
                {
                    throw new InvalidCastException("No end quotation mark for base64 encoding found!");
                }
            }
            else if (json[currentReadIndex] == 'n' &&
                     json[currentReadIndex + 1] == 'u' &&
                     json[currentReadIndex + 2] == 'l' &&
                     json[currentReadIndex + 3] == 'l')
            {
                currentReadIndex += 4;
                return(null);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Example #7
0
        public object ReadValue(IStreamReader reader, ISerializeContext context)
        {
            byte contentType = reader.ReadUInt8();

            context.Key = this.Name;

            if (contentType == ValueItem.CollectionObjectIdent)
            {
                int count = reader.ReadInt32();

                if (isArray)
                {
                    Array array = Array.CreateInstance(itemType, count);

                    if (isByteArray)
                    {
                        return(reader.ReadBytes(count).ToArray());
                    }
                    else
                    {
                        for (int i = 0; i < count; i++)
                        {
                            context.ArrayIndex = i;
                            var item = itemStructure.ReadValue(reader, context);
                            array.SetValue(item, i);
                        }
                        context.ArrayIndex = null;
                    }
                    return(array);
                }
                else if (implementsIList)
                {
                    IList coll = (IList)TypeService.CreateInstance(targetCollectionType);

                    for (int i = 0; i < count; i++)
                    {
                        context.ArrayIndex = i;
                        var item = itemStructure.ReadValue(reader, context);
                        coll.Add(item);
                    }
                    context.ArrayIndex = null;

                    return(coll);
                }
                else
                {
                    object specialColl = TypeService.CreateInstance(targetCollectionType);

                    for (int i = 0; i < count; i++)
                    {
                        context.ArrayIndex = i;
                        var item = itemStructure.ReadValue(reader, context);
                        specialCollAddMethod.Invoke(specialColl, new object[] { item });
                    }
                    context.ArrayIndex = null;

                    return(specialColl);
                }
            }
            else if (contentType == ValueItem.NullValueIdent)
            {
                return(null);
            }
            else if (contentType == ValueItem.TypeMetaInfo)
            {
                TypeMetaStructure.SkipTypeMetaInfo(reader);
                return(this.ReadValue(reader, context));
            }
            else
            {
                throw new InvalidOperationException($"Type ident {contentType} not expected!");
            }
        }