// --------------------------------------------------

        // --------------------------------------------------

        object[] GetPropertyValues(L3TypeManager typeManager)
        {
            if (typeManager.SelectedPropertyTypeManagers == null)
            {
                return(new object[0]);
            }

            int l = typeManager.SelectedPropertyTypeManagers.Length;

            object[] propertyValues = new object[l];

            for (int ipi = 0; ipi < l; ipi++)
            {
                var _tm = typeManager.SelectedPropertyTypeManagers[ipi];
                if (_tm == null)
                {
                    _tm =
                        typeManager.SelectedPropertyTypeManagers[ipi] =
                            this.typeManagerCollection.GetTypeManager(
                                typeManager.l2TypeManager.L1TypeManager.type,
                                null, true, true);
                    typeManager.l2TypeManager.SelectedPropertyTypeManagers[ipi] = _tm.l2TypeManager;
                }
                var propValue = this.LookForObjectAndManagesChannels(_tm, null, null, false);

                propertyValues[ipi] = propValue;
            }
            return(propertyValues);
        }
Beispiel #2
0
        // -------------------------------------------------------------------------------

        /// <summary>
        /// Creates a container for this object, if any, and returns the container instance and type.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="typeManager"></param>
        /// <param name="containerTypeManager">TypeManager of the container.</param>
        /// <returns></returns>
        internal object CreateAContainerIfNecessary(
            object obj,
            L3TypeManager typeManager,
            out L3TypeManager containerTypeManager)
        {
            ITypeContainer container = typeManager.l2TypeManager.Container;

            if (container == null)
            {
                containerTypeManager = null;
                return(null);
            }

            var obj2 = container.CreateNewContainer(obj);

            if (obj2 == null)
            {
                typeManager.l2TypeManager.Container = null;                 // The transcoder of this type is invalid. We do not use this container anymore.
                containerTypeManager = null;
                return(obj);
            }

            containerTypeManager = l3typeManagerCollection.GetTypeManager(obj2.GetType(), this, true, false);
            return(obj2);
        }
        // --------------------------------------------------

        object[] GetFieldValues(L3TypeManager typeManager)
        {
            if (typeManager.SelectedFieldTypeManagers == null)
            {
                return(new object[0]);
            }

            int l = typeManager.SelectedFieldTypeManagers.Length;

            object[] fieldValues = new object[l];

            for (int ifi = 0; ifi < l; ifi++)
            {
                var _tm = typeManager.SelectedFieldTypeManagers[ifi];
                if (_tm == null)
                {
                    _tm =
                        typeManager.SelectedFieldTypeManagers[ifi] =
                            this.typeManagerCollection.GetTypeManager(
                                typeManager.l2TypeManager.SelectedFields[ifi].FieldType,
                                null, true, true);
                    typeManager.l2TypeManager.SelectedFieldTypeManagers[ifi] =
                        _tm.l2TypeManager;
                }
                var fieldValue = this.LookForObjectAndManagesChannels(
                    _tm
                    , null
                    , null
                    , false
                    );
                fieldValues[ifi] = fieldValue;
            }
            return(fieldValues);
        }
        internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
        {
            if (!GetNextXmlPart())
            {
                throw new Exception();
            }

            if (this.xmlReader.NodeType == XmlNodeType.EndElement)
            {
#if DEBUG
                if (typeManager.l2TypeManager.L1TypeManager.type != typeof(string))
                {
                    throw new Exception();
                }
#endif
                return(DeserializationFormatter.NoValue);
            }

#if DEBUG
            if (this.xmlReader.NodeType != XmlNodeType.Text)
            {
                throw new Exception();
            }
#endif
            var rawValue = this.xmlReader.Value;
            return(DeserializationFormatter.TranscodeStringToPrimitiveObject(rawValue, typeManager));
        }
        internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
        {
#if DEBUG
            if (typeManager == null)
            {
                throw new Exception();
            }
#endif

            return(base.ReadPrimitiveObjectFromBinaryStream(this.binaryReader, typeManager, this.parameters.CompressIntsAs7Bits));
        }
        internal Object Deserialize()
        {
            if (this.DataEndMarkHasBeenPassed)
            {
                throw new EndOfStreamException();
            }
            this.DataEndMarkHasBeenPassed = false;
            this.instancesChannel         = new InstancesChannel();
            if (this.stream.CanSeek)
            {
                if (this.stream.Position == this.stream.Length)
                {
                    this.stream.Position = 0;
                }
                this.SetStreamPosition(this.stream.Position); // Useful if any cache memory.
            }

            this.PassPreamble();

            if (this.typeManagerCollection == null)
            {
                this.typeManagerCollection =
                    new L3TypeManagerCollection(this.parameters.customModifiers, this.Version);
            }

            this.TypeDescriptorTypeManager = this.typeManagerCollection.GetTypeManager((int)SerializationFormatter.CompulsoryType.SerializationTypeDescriptorIndex);

            if (this.Version == StreamFormatVersion.Version3_0)
            {
                // We load the Header (new in version 3.0):

                Header header = (Header)this.LookForObjectAndManagesChannels(
                    this.typeManagerCollection.GetTypeManager((int)SerializationFormatter.CompulsoryType.HeaderIndex),
                    null, null, false);

                // now we try to load these assemblies:
                foreach (var ai in header.AssemblyIdentifiers)
                {
                    ai.Load();
                }
            }

            object o = this.LookForObjectAndManagesChannels(null, null, null, false);

            if (!this.DataEndMarkHasBeenPassed)
            {
                this.PassDataEndMark();
            }
            this.PassTreeEndTag();

            return(o);
        }
		// TODO: write a generic method for each Primitive type, in order to avoid boxing to object.
		internal static Object TranscodeStringToPrimitiveObject(string s, L3TypeManager typeManager)
		{
			TypeCode tc = (TypeCode)typeManager.TypeIndex;
#if DEBUG
			if ((int)tc < (int)TypeCode.Boolean)
				throw new ArgumentException("data is not a Primitive type");
#endif
			switch (tc)
			{
				case TypeCode.Boolean:
					return Boolean.Parse(s);
				case TypeCode.Byte:
					return Byte.Parse(s);
				case TypeCode.Char:
#if SILVERLIGHT || PORTABLE
                    return s[0];
#else
					return Char.Parse(s);
#endif
				case TypeCode.DateTime:
					return new DateTime(long.Parse(s));
				case TypeCode.Decimal:
					return Decimal.Parse(s, Tools.EnUSCulture);
				case TypeCode.Double:
					return Double.Parse(s, Tools.EnUSCulture);
				case TypeCode.Int16:
					return Int16.Parse(s);
				case TypeCode.Int32:
					return Int32.Parse(s);
				case TypeCode.Int64:
					return Int64.Parse(s);
				case TypeCode.SByte:
					return SByte.Parse(s);
				case TypeCode.Single:
					return Single.Parse(s, Tools.EnUSCulture);
				case TypeCode.String:
					return s;
				case TypeCode.UInt16:
					return UInt16.Parse(s);
				case TypeCode.UInt32:
					return UInt32.Parse(s);
				case TypeCode.UInt64:
					return UInt64.Parse(s);
				default:
					throw new Exception();
			}
		}
            internal static IDictionary CreateFromGenericIDictionary(
                object obj, L3TypeManager typeManager)
            {
                {
                    IDictionary idict = obj as IDictionary;
                    if (idict != null)                     // example: Dictionary<,> is a IDictionary.
                    {
                        return(idict);
                    }
                }
                var  t2 = typeof(GenericIDictionaryBoxer <,>);
                Type t  = t2.MakeGenericType(new Type[] {
                    typeManager.DictionaryKeysTypeManager.l2TypeManager.L1TypeManager.type,
                    typeManager.DictionaryValuesTypeManager.l2TypeManager.L1TypeManager.type
                });                                                                                                  // TODO: put this type in cache.

                return((IDictionary)Activator.CreateInstance(t, new object[] { obj }));
            }
        // --------------------------------------------------

        /// <summary>
        ///
        /// </summary>
        /// <returns>Deserialized object, or ElementTypes.TypesChannelSection if some type has been described, or null if no more elements have been found, or InstanceNotReadyAndListOfNeeds if instance is not available yet.</returns>
        Object LookForObjectAndManagesChannels(
            L3TypeManager WantedType,
            object AlreadyInstanciatedCollectionOrDictionary, // For inner collection or dictionary.
            long?NumberOfElements,                            // For inner collection or dictionary.
            bool AddToTheInstances)
        {
            object obj = this._LookForObjectAndManagesChannels(
                WantedType,
                AlreadyInstanciatedCollectionOrDictionary, NumberOfElements, AddToTheInstances);

            var obj2 = obj as ITypeContainer;

            if (obj2 != null)
            {
                var obj3 = obj2.Deserialize();
                return(obj3);
            }
            return(obj);
        }
		/// <summary>
		/// If the right element is not found, an exception occures.
		/// Optionnaly, We can accept a channel section.
		/// </summary>
		internal abstract bool GetNextElementAs(
			ref Element e,
			bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement);
        internal override bool GetNextElementAs(
            ref Element e,
            bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement)
        {
            bool SupposedTypeNumberIsKnown = SupposedType != null;

            // There is no tag for value primitive types:
            if (SupposedTypeNumberIsKnown &&
                SupposedType.TypeIndex < (int)TypeCode.String &&
                SupposedType.TypeIndex >= (int)TypeCode.Boolean)
            {
                e.ContainsAValue   = true;
                e.ElementType      = ElementTypes.PrimitiveValue;
                e.IsAClosingTag    = true;
                e.typeIndex        = SupposedType.TypeIndex;
                e.typeIndexIsKnown = true;
                return(true);
            }

            // There is no tag for structures:
            if (SupposedTypeNumberIsKnown &&
                SupposedType.TypeIndex != (int)TypeCode.Object &&
                SupposedType.l2TypeManager.L1TypeManager.IsStructure &&
                (SupposedType.l2TypeManager.Container == null) &&
                !SupposedType.l2TypeManager.L1TypeManager.IsNullable)
            {
                e.ContainsAValue   = false;
                e.ElementType      = ElementTypes.SubBranch;
                e.IsAClosingTag    = true;
                e.typeIndex        = SupposedType.TypeIndex;
                e.typeIndexIsKnown = true;
                return(true);
            }



            // 1) Element code : byte
            //int b = this.binaryReader.BaseStream.ReadByte(); // Unlike this.binaryReader.ReadByte(), this function does not cause an exception (exceptions can prevent method inlining).
            int b = this.binaryReader.ReadByteNoException();             // Unlike this.binaryReader.ReadByte(), this function does not cause an exception (exceptions can prevent method inlining).

            if (b < 0)
#if DEBUG
            { throw new EndOfStreamException(); }
#else
            { return(false);                  // end of file.
            }
#endif
            byte elementCode = unchecked ((byte)b);
            if (elementCode == BinarySerializationFormatter.DataEndMarkCode)
            {
                return(false);                // end of file.
            }
            ElementTypes et = (ElementTypes)(elementCode & (byte)BinaryElementCode.BitMask);

#if DEBUG
            if (!AcceptChannelSection &&
                !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
            {
                throw new Exception();
            }
#endif

            // 2) typeNumber : 7 bit-compressed int
            bool HasTypeNumber = (elementCode & (byte)BinaryAttributeCode.HasATypeNumber) != 0;

#if DEBUG
            if (!SupposedTypeNumberIsKnown && !HasTypeNumber &&
                (elementCode == (byte)BinaryElementCode.PrimitiveValue || elementCode == (byte)BinaryElementCode.SubBranch))
            {
                throw new Exception();
            }
#endif

            int typeNumber =
                HasTypeNumber ?
                this.binaryReader.Read7BitEncodedInt()
                                : (SupposedTypeNumberIsKnown ? SupposedType.TypeIndex : 0);

            // 3) Reference InstanceIndex : 7 bit-compressed int
            int?InstanceNumber =
                et == ElementTypes.Reference ?
                this.binaryReader.Read7BitEncodedInt()
                                : (int?)null;

            // 4) NumberOfElements : 7 bit-compressed long
            bool HasANumberOfElements = (elementCode & (byte)BinaryAttributeCode.HasANumberOfElements) != 0;
            long?numberOfElements     =
                HasANumberOfElements ?
                this.binaryReader.Read7BitEncodedLong()
                                : (long?)null;
#if DEBUG
            if (HasANumberOfElements && et != ElementTypes.SubBranch)
            {
                Debugger.Break();
            }
#endif

            e.ElementType = et;
#if DEBUG
            e.Name = Name;
#endif
            e.typeIndexIsKnown = SupposedTypeNumberIsKnown | HasTypeNumber;
            e.typeIndex        = typeNumber;
            e.InstanceIndex    = InstanceNumber;
            e.IsAClosingTag    = true;
            e.NumberOfElements = numberOfElements;
            e.ContainsAValue   = et == ElementTypes.PrimitiveValue;
            return(true);
        }
Beispiel #12
0
        // ---------------------------------------------

        void AddACollection(
            ref ChannelInfos channelInfos,
            IEnumerable iEnumerable,
            L3TypeManager collectionTypeManager,
            string NameToWrite = null)
        {
            if (collectionTypeManager.l2TypeManager.L1TypeManager.type.IsArray)
            {
                Array array = iEnumerable as Array;
                if (array.Rank != 1)
                {
                    throw new Exception(ErrorMessages.GetText(1));                     // "This version of UniversalSerializer can not manage multi-dimentionnal arrays."
                }
                // TODO: create a Container for complex arrays (multidimensional and not-0-based, see Array.GetLowerBound()).
            }


            Type          collectionType = iEnumerable.GetType();
            L3TypeManager typeManager    =
                collectionTypeManager.l2TypeManager.L1TypeManager.type == collectionType ?
                collectionTypeManager
                                : this.l3typeManagerCollection.GetTypeManager(collectionType, this, true, false);
            int collectionTypeNumber =
                typeManager.TypeIndex;

            if (iEnumerable.IsEmpty())
            {
                // Optimisation: we only write an empty object as a collection.
                this.ChannelAddNull(
                    ref channelInfos
                    );

                return;
            }

            Type CommonItemType =             // can be null.
                                  typeManager.CollectionItemsTypeManager != null ?
                                  typeManager.CollectionItemsTypeManager.l2TypeManager.L1TypeManager.type
                                : null;

            this.ChannelEnterCollection(
                ref channelInfos
#if DEBUG
                , NameToWrite
#endif
#if DEBUG
                , collectionType
#endif
                );
            var CommonItemTM         = typeManager.CollectionItemsTypeManager;
            int?CommonItemTypeNumber =
                CommonItemTM != null ?
                CommonItemTM.TypeIndex
                                : (int?)null;


            if (CommonItemTM == null || CommonItemTM.l2TypeManager.IsClass || TypeTools.TypeEx.IsInterface(CommonItemTM.l2TypeManager.L1TypeManager.type))
            {
                // For item types that are not-sealed classes or interfaces:

                // item of foreach can not be referenced. Therefore we enumerate manually:
                var enumerator = iEnumerable.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    var item = enumerator.Current;
                    if (item != null)
                    {
                        Type          itemType = item.GetType();
                        L3TypeManager itemTm   =
                            itemType != CommonItemType?
                            this.l3typeManagerCollection.GetTypeManager(item.GetType(), this, true, false)                             // Items can have different types, even if all items inherit the same type.
                                : CommonItemTM;

                        int  ItemTypeNumber  = itemTm.TypeIndex;
                        bool WriteTypeNumber = (ItemTypeNumber != CommonItemTypeNumber);                         // We write the type index only if it is different from the common type index.

                        this.AddAnObject(ref channelInfos, item, null, ItemTypeNumber, itemTm, false, WriteTypeNumber);
                    }
                    else
                    {
                        this.ChannelAddNull(
                            ref channelInfos
                            );
                    }
                }
            }
            else             // structures or sealed classes can not inherit therefore can be serialized faster (because we don't have to specify the item type):
            {
#if !DEBUG && !WINDOWS_UWP
                if (CommonItemTypeNumber != null)
                {
                    // Using a generic IEnumerable is a bit quicker (11 % on .NET 4.5).
                    var mi2 = gfAddAllStructs.MakeGenericMethod(CommonItemType);
                    mi2.Invoke(this, new object[] {
                        iEnumerable, channelInfos, CommonItemTypeNumber.Value, CommonItemTM
                    });
                }
                else
#endif
                {
                    // The normal algorithm makes debugging easier.
                    // item of foreach can not be referenced. Therefore we enumerate manually:
                    var enumerator = iEnumerable.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        var item = enumerator.Current;
                        this.AddAnObject(ref channelInfos, item, null, CommonItemTypeNumber.Value, CommonItemTM, false, false);
                    }
                }
            }
            this.ChannelExitCollection(ref channelInfos);
        }
		[System.Runtime.CompilerServices.MethodImpl((System.Runtime.CompilerServices.MethodImplOptions)256)] // AggressiveInlining
		internal override bool GetNextElementAs(
			ref Element e,
			bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement)
		{
			int? SupposedTypeNumber = SupposedType != null ? SupposedType.TypeIndex : (int?)null;

			if (!this.GetNextXmlPart())
				if (NeedsThisElement)
					throw new Exception();
				else
					return false; // end of document.

			if (this.xmlReader.Name == XmlSerializationFormatter.DataEndMarkTag)
				return false; // end of document.

			ElementTypes? et2 = this.GetElementType();
			if (et2 == null)
			{
#if DEBUG
				if (this.xmlReader.NodeType != XmlNodeType.EndElement && this.xmlReader.Name != "data")
					Debugger.Break();
#endif
				return false;
			}
			ElementTypes et = et2.Value;

			if (WantClosingElement && this.xmlReader.NodeType == XmlNodeType.Element)
				if (NeedsThisElement)
					throw new Exception();
				else
					return false;

#if DEBUG
			if (!AcceptChannelSection
						&& !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
				throw new Exception();


			// Checks name correspondance:
			string name = this.xmlReader.GetAttribute(XmlAttributeName.Name);
			if (Name != null && name != null && name != Name)
				throw new Exception();
#endif

			string typeNumber = this.xmlReader.GetAttribute(XmlAttributeName.TypeNumber);
#if DEBUG
			// Checks type correspondance:
			if (typeNumber != null && typeNumber != string.Empty && SupposedTypeNumber != null)
			{
				int foundTypeNumber = int.Parse(typeNumber);
				if (foundTypeNumber != SupposedTypeNumber.Value)
				{
					var found = this.typeManagerCollection.GetTypeManager(foundTypeNumber);
					var foundGtd = found.l2TypeManager.L1TypeManager;
					if (!foundGtd.type.Is(typeof(ITypeContainer)))
					{
						var supposed = this.typeManagerCollection.GetTypeManager(SupposedTypeNumber.Value);
						var supposedGtd = supposed.l2TypeManager.L1TypeManager;
						if (!foundGtd.type.Is(supposedGtd.type))
							if (!supposedGtd.IsNullable || supposedGtd.type.GetGenericArguments().Length == 0 || !foundGtd.type.Is(supposedGtd.type.GetGenericArguments()[0]))
								throw new Exception();
					}
				}
			}
#endif
			int? tn =
				typeNumber != null ? (
				int.Parse(typeNumber))
				: SupposedTypeNumber;

			string inum = this.xmlReader.GetAttribute(XmlAttributeName.InstanceIndex);
			int? InstanceNumber =
				inum != null ?
				int.Parse(inum)
				: (int?)null;

			string noe = this.xmlReader.GetAttribute(XmlAttributeName.NumberOfElements);
			long? numberOfElements =
				noe != null ?
				long.Parse(noe)
				: (long?)null;

			e.ContainsAValue = !this.xmlReader.IsEmptyElement;
			e.ElementType = et;
			e.InstanceIndex = InstanceNumber;
			e.IsAClosingTag = this.xmlReader.NodeType == XmlNodeType.EndElement;
#if DEBUG
			e.Name = name != null ? name : Name;
#endif
			e.NeedsAnEndElement = !this.xmlReader.IsEmptyElement;
			e.NumberOfElements = numberOfElements;
			if (tn != null)
			{
				e.typeIndex = tn.Value;
				e.typeIndexIsKnown = true;
			}

			return true;
		}
		// ------------------------------

		/// <summary>
		/// If the right element is not found, an exception occures.
		/// We can propose one or two element types.
		/// </summary>
		internal override bool GetNextElementAs(
			ref Element e,
			bool AcceptChannelSection, string SupposedName, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement
)
		{
			int? SupposedTypeNumber = SupposedType != null ? SupposedType.TypeIndex : (int?)null;

			if (!this.GetNextJSONPart())
				if (NeedsThisElement)
					throw new Exception();
				else
					return false;

			if (this._JSONReader.Name == JSONSerializationFormatter.DataEndMarkTag)
			{
				WeAlreadyObtainedJSONPart = true;
				this.PassDataEndMark();
				return false;
			}

			ElementTypes? et2 = this.GetElementType();
			if (et2 == null)
			{
#if DEBUG
				if (this._JSONReader.NodeType != XmlNodeType.EndElement && this._JSONReader.Name != "data")
					Debugger.Break();
#endif
				return false;
			}
			ElementTypes et = et2.Value;

			if (WantClosingElement && this._JSONReader.NodeType == XmlNodeType.Element)
				if (NeedsThisElement)
					throw new Exception();
				else
					return false;

#if DEBUG
			if (!AcceptChannelSection
						&& !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
				throw new Exception();
#endif



#region Analyse attributes
			// Contrary to xml, json does not have attributes. We have to take the right elements as attribute replacement, analysing its name.

			int? tn = null;
			int? InstanceNumber = null;
			long? numberOfElements = null;
#if DEBUG
			string name = null;
#endif

			while (this.GetNextJSONPart())
			{
				int iattribute = ((IList<string>)JSONSerializationFormatter.JSONAttributeNames).IndexOf(this._JSONReader.Name);
				if (iattribute < 0)
					break;

				{
					AttributeTypes at = (AttributeTypes)iattribute; // more clear.

					switch (at)
					{

						case AttributeTypes.InstanceIndex:
							{
								string inum = this.JSONGetValue();
								InstanceNumber =
									inum != null ?
									int.Parse(inum)
									: (int?)null;
							}
							break;


						case AttributeTypes.TypeNumber:
							{
								string typeNumber = this.JSONGetValue();
#if DEBUG
								// Checks type correspondance:
								if (typeNumber != null && typeNumber != string.Empty && SupposedTypeNumber != null)
								{
									int foundTypeNumber = int.Parse(typeNumber);
									if (foundTypeNumber != SupposedTypeNumber.Value)
									{
										var found = base.typeManagerCollection.GetTypeManager(foundTypeNumber);
										var foundGtd = found.l2TypeManager.L1TypeManager;
										if (!foundGtd.type.Is(typeof(ITypeContainer)))
										{
											var supposed = base.typeManagerCollection.GetTypeManager(SupposedTypeNumber.Value);
											var supposedGtd = supposed.l2TypeManager.L1TypeManager;
											if (!foundGtd.type.Is(supposedGtd.type))
												if (!supposedGtd.IsNullable || supposedGtd.type.GetGenericArguments().Length == 0 || !foundGtd.type.Is(supposedGtd.type.GetGenericArguments()[0]))
													throw new Exception();
										}
									}
								}
#endif
								tn =
									typeNumber != null ? (
									int.Parse(typeNumber))
									: SupposedTypeNumber;
							}
							break;

						case AttributeTypes.NumberOfElements:
							{
								string noe = this.JSONGetValue();
								numberOfElements =
									noe != null ?
									long.Parse(noe)
									: (long?)null;
							}
							break;

#if DEBUG
						case AttributeTypes.Name:
							{
								name = this.JSONGetValue();

								// Checks name correspondance:
								if (SupposedName != null && name != null && name != SupposedName)
									throw new Exception();
							}
							break;

						case AttributeTypes.TypeName:
							{
								string typeName = this.JSONGetValue();
							}
							break;
						default:
							throw new Exception();
#endif
					}
				}
			}
			WeAlreadyObtainedJSONPart = true; // the previous read element is kept for following process.
#endregion Analyse attributes

			this.GetNextJSONPart();
			this.WeAlreadyObtainedJSONPart=true;
			bool ContainsAValue = this._JSONReader.NodeType != XmlNodeType.EndElement;

			e.ContainsAValue = ContainsAValue;		
			e.ElementType = et;
			e.InstanceIndex = InstanceNumber;
			e.IsAClosingTag = this._JSONReader.NodeType == XmlNodeType.EndElement;			
#if DEBUG
			e.Name= name != null ? name : SupposedName;
#endif
			e.NeedsAnEndElement = !this._JSONReader.IsEmptyElement;
			e.NumberOfElements = numberOfElements;
			if (tn != null)
			{
				e.typeIndex = tn.Value;
				e.typeIndexIsKnown = true;
			}
			return true;
		}
Beispiel #15
0
        // TODO: write a generic method for each Primitive type, in order to avoid boxing to object.
        internal Object ReadPrimitiveObjectFromBinaryStream(BinaryReader2 binaryReader, L3TypeManager typeManager, bool CompressIntsAs7Bits)
        {
            TypeCode tc = (TypeCode)typeManager.TypeIndex;

#if DEBUG
            if ((int)tc < (int)TypeCode.Boolean)
            {
                throw new ArgumentException(ErrorMessages.GetText(9));                //"data is not a Primitive type");
            }
#endif
            switch (tc)
            {
            case TypeCode.Boolean:
                return(binaryReader.ReadBoolean());

            case TypeCode.Byte:
                return(binaryReader.ReadByte());

            case TypeCode.Char:
                return(binaryReader.ReadChar());

            case TypeCode.DateTime:
                return(Tools.DateTimeFromTicksAndKind(binaryReader.ReadUInt64()));

            case TypeCode.Decimal:
                return(binaryReader.ReadDecimal());

            case TypeCode.Double:
                return(binaryReader.ReadDouble());

            case TypeCode.SByte:
                return(binaryReader.ReadSByte());

            case TypeCode.Single:
                return(binaryReader.ReadSingle());

            case TypeCode.String:
                return(binaryReader.ReadString());

            case TypeCode.Int16:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.ReadSpecial7BitEncodedShort());
                }
                else
                {
                    return(binaryReader.ReadInt16());
                }

            case TypeCode.Int32:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.ReadSpecial7BitEncodedInt());
                }
                else
                {
                    return(binaryReader.ReadInt32());
                }

            case TypeCode.Int64:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.ReadSpecial7BitEncodedLong());
                }
                else
                {
                    return(binaryReader.ReadInt64());
                }

            case TypeCode.UInt16:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.Read7BitEncodedUShort());
                }
                else
                {
                    return(binaryReader.ReadUInt16());
                }

            case TypeCode.UInt32:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.Read7BitEncodedUInt());
                }
                else
                {
                    return(binaryReader.ReadUInt32());
                }

            case TypeCode.UInt64:
                if (CompressIntsAs7Bits)
                {
                    return(binaryReader.Read7BitEncodedULong());
                }
                else
                {
                    return(binaryReader.ReadUInt64());
                }

            default:
#if DEBUG
                throw new Exception();
#else
                return(null);
#endif
            }
        }
Beispiel #16
0
 internal abstract Object GetSimpleValueInElement(L3TypeManager typeManager);
Beispiel #17
0
        // ------------------------------

        /// <summary>
        /// If the right element is not found, an exception occures.
        /// We can propose one or two element types.
        /// </summary>
        internal override bool GetNextElementAs(
            ref Element e,
            bool AcceptChannelSection, string SupposedName, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement
            )
        {
            int?SupposedTypeNumber = SupposedType != null ? SupposedType.TypeIndex : (int?)null;

            if (!this.GetNextJSONPart())
            {
                if (NeedsThisElement)
                {
                    throw new Exception();
                }
                else
                {
                    return(false);
                }
            }

            if (this._JSONReader.Name == JSONSerializationFormatter.DataEndMarkTag)
            {
                WeAlreadyObtainedJSONPart = true;
                this.PassDataEndMark();
                return(false);
            }

            ElementTypes?et2 = this.GetElementType();

            if (et2 == null)
            {
#if DEBUG
                if (this._JSONReader.NodeType != XmlNodeType.EndElement && this._JSONReader.Name != "data")
                {
                    Debugger.Break();
                }
#endif
                return(false);
            }
            ElementTypes et = et2.Value;

            if (WantClosingElement && this._JSONReader.NodeType == XmlNodeType.Element)
            {
                if (NeedsThisElement)
                {
                    throw new Exception();
                }
                else
                {
                    return(false);
                }
            }

#if DEBUG
            if (!AcceptChannelSection &&
                !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
            {
                throw new Exception();
            }
#endif



            #region Analyse attributes
            // Contrary to xml, json does not have attributes. We have to take the right elements as attribute replacement, analysing its name.

            int? tn               = null;
            int? InstanceNumber   = null;
            long?numberOfElements = null;
#if DEBUG
            string name = null;
#endif

            while (this.GetNextJSONPart())
            {
                int iattribute = ((IList <string>)JSONSerializationFormatter.JSONAttributeNames).IndexOf(this._JSONReader.Name);
                if (iattribute < 0)
                {
                    break;
                }

                {
                    AttributeTypes at = (AttributeTypes)iattribute;                     // more clear.

                    switch (at)
                    {
                    case AttributeTypes.InstanceIndex:
                    {
                        string inum = this.JSONGetValue();
                        InstanceNumber =
                            inum != null?
                            int.Parse(inum)
                                : (int?)null;
                    }
                    break;


                    case AttributeTypes.TypeNumber:
                    {
                        string typeNumber = this.JSONGetValue();
#if DEBUG
                        // Checks type correspondance:
                        if (typeNumber != null && typeNumber != string.Empty && SupposedTypeNumber != null)
                        {
                            int foundTypeNumber = int.Parse(typeNumber);
                            if (foundTypeNumber != SupposedTypeNumber.Value)
                            {
                                var found    = base.typeManagerCollection.GetTypeManager(foundTypeNumber);
                                var foundGtd = found.l2TypeManager.L1TypeManager;
                                if (!foundGtd.type.Is(typeof(ITypeContainer)))
                                {
                                    var supposed    = base.typeManagerCollection.GetTypeManager(SupposedTypeNumber.Value);
                                    var supposedGtd = supposed.l2TypeManager.L1TypeManager;
                                    if (!foundGtd.type.Is(supposedGtd.type))
                                    {
                                        if (!supposedGtd.IsNullable || supposedGtd.type.GetGenericArguments().Length == 0 || !foundGtd.type.Is(supposedGtd.type.GetGenericArguments()[0]))
                                        {
                                            throw new Exception();
                                        }
                                    }
                                }
                            }
                        }
#endif
                        tn =
                            typeNumber != null ? (
                                int.Parse(typeNumber))
                                                                        : SupposedTypeNumber;
                    }
                    break;

                    case AttributeTypes.NumberOfElements:
                    {
                        string noe = this.JSONGetValue();
                        numberOfElements =
                            noe != null?
                            long.Parse(noe)
                                : (long?)null;
                    }
                    break;

#if DEBUG
                    case AttributeTypes.Name:
                    {
                        name = this.JSONGetValue();

                        // Checks name correspondance:
                        if (SupposedName != null && name != null && name != SupposedName)
                        {
                            throw new Exception();
                        }
                    }
                    break;

                    case AttributeTypes.TypeName:
                    {
                        string typeName = this.JSONGetValue();
                    }
                    break;

                    default:
                        throw new Exception();
#endif
                    }
                }
            }
            WeAlreadyObtainedJSONPart = true;             // the previous read element is kept for following process.
            #endregion Analyse attributes

            this.GetNextJSONPart();
            this.WeAlreadyObtainedJSONPart = true;
            bool ContainsAValue = this._JSONReader.NodeType != XmlNodeType.EndElement;

            e.ContainsAValue = ContainsAValue;
            e.ElementType    = et;
            e.InstanceIndex  = InstanceNumber;
            e.IsAClosingTag  = this._JSONReader.NodeType == XmlNodeType.EndElement;
#if DEBUG
            e.Name = name != null ? name : SupposedName;
#endif
            e.NeedsAnEndElement = !this._JSONReader.IsEmptyElement;
            e.NumberOfElements  = numberOfElements;
            if (tn != null)
            {
                e.typeIndex        = tn.Value;
                e.typeIndexIsKnown = true;
            }
            return(true);
        }
Beispiel #18
0
        // ------------------------------

        internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
        {
            if (!GetNextJSONPart())
            {
                throw new Exception();
            }
            if (this._JSONReader.NodeType == XmlNodeType.EndElement)
            {             // empty 'e' element.
                this.WeAlreadyObtainedJSONPart = true;
                return(null);
            }
#if DEBUG
            if (this._JSONReader.NodeType != XmlNodeType.Element || this._JSONReader.Name != "a:item")
            {
                throw new Exception();
            }
#endif

            {
                if (!GetNextJSONPart())
                {
                    throw new Exception();
                }
#if DEBUG
                if (this._JSONReader.NodeType != XmlNodeType.Text || this._JSONReader.Name != string.Empty)
                {
                    throw new Exception();
                }
#endif
            }

            string rawValue;
            {
                // JsonReaderWriterFactory is very special: it splits string when it encounters a special character.
                // Therfore, we need to concatenate this parts.

                var Texts = new StringBuilder(this._JSONReader.Value);
                while (GetNextJSONPart())
                {
                    if (this._JSONReader.NodeType != XmlNodeType.Text)
                    {
                        this.WeAlreadyObtainedJSONPart = true;
                        break;
                    }
                    Texts.Append(this._JSONReader.Value);
                }
                rawValue = Texts.ToString();
            }

            {             // passes EndElement:
                if (!GetNextJSONPart())
                {
                    throw new Exception();
                }
#if DEBUG
                if (this._JSONReader.NodeType != XmlNodeType.EndElement || this._JSONReader.Name != "a:item")
                {
                    throw new Exception();
                }
#endif
            }

            return(DeserializationFormatter.TranscodeStringToPrimitiveObject(rawValue, typeManager));
        }
Beispiel #19
0
        void AddAComplexObject(ref ChannelInfos channelInfos, object obj,
#if DEBUG
                               string NameToWrite,
#endif
                               int TypeNumber, L3TypeManager tm, bool WriteType)
        {
#if DEBUG
            if (tm == null)
            {
                Debugger.Break();
            }
#endif

            {
                L3TypeManager tm2  = null;
                var           obj2 = this.CreateAContainerIfNecessary(obj, tm, out tm2);
                if (tm2 != null)
                {
                    tm         = tm2;
                    TypeNumber = tm2.TypeIndex;
                    WriteType  = true;
                    obj        = obj2;
                }
            }

            #region Manages instances
            bool typeToBeSerializedIsAClass = tm.l2TypeManager.IsClass;
            if (typeToBeSerializedIsAClass && channelInfos.ChannelNumber != ChannelNumber.TypeDescriptorsChannel)
            {
                IndexClass index;
                if (!this.ClassInstanceIndexes.TryGetValue(obj, out index))
                {
                    index = new IndexClass(this.AddObjToKnownInstances(obj));

                    // serialize the object at the root of the Instances branch:
                    this.AddAComplexObject_NoInstanceTest(
                        ref this.channelInfos[(int)ChannelNumber.InstancesChannel],
                        obj,
#if DEBUG
                        NameToWrite,
#endif
                        tm, true,
                        true);                         // For an instance, the type is always wrote.
                }
                // Replace instance by a reference:
                this._ChannelAddReference(
                    ref channelInfos,
#if DEBUG
                    NameToWrite,
#endif
                    index.Value
#if DEBUG
                    , this.l3typeManagerCollection.GetTypeManager(TypeNumber).l2TypeManager.L1TypeManager.type
#endif
                    );
                return;
            }
            #endregion Manages instances

            // We serialize the complex object:
            AddAComplexObject_NoInstanceTest(ref channelInfos, obj,
#if DEBUG
                                             NameToWrite,
#endif
                                             tm, false, WriteType);
        }
Beispiel #20
0
        void AddAComplexObject_NoInstanceTest(
            ref ChannelInfos channelInfos, object obj,
#if DEBUG
            string NameToWrite,
#endif
            L3TypeManager typeManager, bool AtRoot, bool WriteType)
        {
            IDictionary AsIDictionary = null;

            bool AddSectionMark = AtRoot && this.parameters.TheStreamingMode == StreamingModes.MultiplexStream;

            if (AddSectionMark)
            {
                this.ChannelEnterChannelSection(ref channelInfos);
            }

            long?NumberOfElements = null;

            if (typeManager.l2TypeManager.L1TypeManager.type.IsArray)
            {
                Array array = obj as Array;
                if (array.Rank != 1)
                {
                    throw new Exception(ErrorMessages.GetText(1));                     // "This version of UniversalSerializer can not manage multi-dimentionnal arrays."
                }
                // TODO: create a Container for complex arrays (not only multidimensional, see Array.GetLowerBound() too).
                NumberOfElements =
#if SILVERLIGHT || PORTABLE || WINDOWS_UWP
                    array.Length;
#else
                    array.GetLongLength(0);
#endif
            }
            else
            if (typeManager.l2TypeManager.L1TypeManager.IsAnObjectIEnumerable)
            {
                NumberOfElements = (obj as IEnumerable).GetCount();
            }
            else
            if (typeManager.l2TypeManager.L1TypeManager.IsADictionary)
            {
                AsIDictionary = obj as IDictionary;
                if (AsIDictionary != null)
                {
                    NumberOfElements = AsIDictionary.Count;
                }
                else
                {
                    AsIDictionary = Tools.GenericIDictionaryBoxer <int, int> .CreateFromGenericIDictionary(obj, typeManager);

                    if (AsIDictionary != null)
                    {
                        NumberOfElements = AsIDictionary.Count;
                    }
                    else
                    {
                        throw new Exception();                         // error.
                    }
                }
            }

            this.ChannelEnterSubBranch(
                ref channelInfos,
                NumberOfElements,
#if DEBUG
                NameToWrite,
#endif
                WriteType ? (int?)typeManager.TypeIndex : null,
                null
#if DEBUG
                , typeManager.l2TypeManager.L1TypeManager.type
#endif
                , typeManager.l2TypeManager.L1TypeManager.IsStructure
                );
            {
                #region serialize the fields.
                if (typeManager.SelectedFieldTypeManagers != null)
                {
                    for (int ifi = 0; ifi < typeManager.SelectedFieldTypeManagers.Length; ifi++)
                    {
                        object fieldValue =
                            typeManager.l2TypeManager.SelectedFieldGetters[ifi](obj);

                        Type FieldType = typeManager.l2TypeManager.SelectedFields[ifi].FieldType;

                        Type t = fieldValue != null?fieldValue.GetType() : FieldType;

                        L3TypeManager _tm;
                        bool          serializable = FieldType == t ? true : l3typeManagerCollection.l2TypeManagerCollection.CanThisTypeBeSerialized(t);
                        if (!serializable)
                        {
                            fieldValue = null;
                        }

                        if (FieldType != t && serializable)
                        {
#if DEBUG
                            if (!t.Is(FieldType))                             // TODO: optimize this test and let it even in relase compilation.
                            {
                                if (!FieldType.Is(typeof(Nullable <>)))
                                {
                                    throw new Exception();
                                }
                            }
#endif
                            _tm = this.l3typeManagerCollection.GetTypeManager(t, this, true, false);
                        }
                        else
                        {
                            _tm = typeManager.SelectedFieldTypeManagers[ifi];
                            if (_tm == null)
                            {
                                _tm =
                                    typeManager.SelectedFieldTypeManagers[ifi] =                                      // updates the TypeManager.
                                                                                 this.l3typeManagerCollection.GetTypeManager(FieldType, this, true, false);
                                typeManager.l2TypeManager.SelectedFieldTypeManagers[ifi] = _tm.l2TypeManager;
                            }
                        }
                        bool WriteTypeNumber = serializable && FieldType != t;

                        this.AddAnObject(ref channelInfos, fieldValue,
                                         null,
                                         _tm.TypeIndex,
                                         _tm, false,
                                         WriteTypeNumber
                                         );
                    }
                }
                #endregion serialize the fields.

                #region serialize the properties.
                if (typeManager.SelectedPropertyTypeManagers != null)
                {
                    // serialize the properties.
                    for (int ipi = 0; ipi < typeManager.SelectedPropertyTypeManagers.Length; ipi++)
                    {
                        var  pi           = typeManager.l2TypeManager.SelectedProperties[ipi];
                        Type propertyType = pi.PropertyType;

                        object propertyValue =
                            typeManager.l2TypeManager.SelectedPropertyGetters[ipi](obj);
                        Type t = propertyValue != null?propertyValue.GetType() : propertyType;

                        L3TypeManager _tm;

                        bool serializable = propertyType == t ? true : l3typeManagerCollection.l2TypeManagerCollection.CanThisTypeBeSerialized(t);
                        if (!serializable)
                        {
                            propertyValue = null;
                        }

                        if (propertyType != t && serializable)
                        {
#if DEBUG
                            if (!t.Is(propertyType))                             // TODO: optimize this test and let it even in relase compilation.
                            {
                                if (!propertyType.Is(typeof(Nullable <>)))
                                {
                                    throw new Exception();
                                }
                            }
#endif
                            _tm = this.l3typeManagerCollection.GetTypeManager(t, this, true, false);
                        }
                        else
                        {
                            _tm = typeManager.SelectedPropertyTypeManagers[ipi];
                            if (_tm == null)
                            {
                                _tm =
                                    typeManager.SelectedPropertyTypeManagers[ipi] =                                      // updates the TypeManager.
                                                                                    this.l3typeManagerCollection.GetTypeManager(propertyType, this, true, false);
                                typeManager.l2TypeManager.SelectedPropertyTypeManagers[ipi] = _tm.l2TypeManager;
                            }
                        }
                        bool WriteTypeNumber = serializable && propertyType != t;

                        this.AddAnObject(ref channelInfos, propertyValue,
                                         null,
                                         _tm.TypeIndex,
                                         _tm, false,
                                         WriteTypeNumber
                                         );
                    }
                }
                #endregion serialize the properties.

                // serialize an inner dictionary:
                if (typeManager.l2TypeManager.L1TypeManager.IsADictionary)
                {
                    this.AddADictionary(
                        ref channelInfos, AsIDictionary, typeManager
                        );
                }

                // serialize an inner collection:
                if (typeManager.l2TypeManager.L1TypeManager.IsAnObjectIEnumerable)
                {
                    this.AddACollection(ref channelInfos, obj as IEnumerable, typeManager
                                        );
                }
            }
            this.ChannelExitSubBranch(ref channelInfos);
            if (AddSectionMark)
            {
                this.ChannelExitChannelSection(ref channelInfos);
            }
        }
Beispiel #21
0
        internal void AddAnObject(
            ref ChannelInfos channelInfos, object obj, string NameToWrite, int TypeNumber, L3TypeManager tm, bool AtRoot, bool WriteType)
        {
#if DEBUG
            if (tm.TypeIndex == (int)TypeCode.Object && obj != null)
            {
                Debugger.Break();
            }
#endif

            bool AddSectionMark = AtRoot && this.parameters.TheStreamingMode == StreamingModes.MultiplexStream;
            if (AddSectionMark)
            {
                this.ChannelEnterChannelSection(ref channelInfos);
            }
            WriteType |= AtRoot && channelInfos.ChannelNumber == SerializationFormatter.ChannelNumber.InstancesChannel;

            if (obj == null)
            {
                this.ChannelAddNull(
                    ref channelInfos
                    );
            }
            else
            if (tm.l2TypeManager.IsAPrimitiveType)
            {
                this.AddPrimitiveElementOrReference(
                    ref channelInfos, obj,
#if DEBUG
                    NameToWrite,
                    tm.l2TypeManager.L1TypeManager.type,
#endif
                    TypeNumber,
                    null,
                    WriteType);
            }
            else
            {
                this.AddAComplexObject(ref channelInfos, obj,
#if DEBUG
                                       NameToWrite,
#endif
                                       TypeNumber, tm, WriteType);
            }

            if (AddSectionMark)
            {
                this.ChannelExitChannelSection(ref channelInfos);
            }
        }
Beispiel #22
0
        // ---------------------------------------------

        void AddADictionary(
            ref ChannelInfos channelInfos,
            IDictionary AsIDictionary,
            L3TypeManager typeManager
            )
        {
            int dictionaryTypeNumber =
                typeManager.TypeIndex;

            if (AsIDictionary.Count == 0)
            {
                // Optimisation: we only write an empty object as a collection.
                this.ChannelAddNull(
                    ref channelInfos
                    );
                return;
            }

            L3TypeManager CommonKeyTM         = typeManager.DictionaryKeysTypeManager;     // can be null.
            L3TypeManager CommonValueTM       = typeManager.DictionaryValuesTypeManager;   // can be null.
            int?          CommonKeyTypeNumber =
                CommonKeyTM != null ?
                CommonKeyTM.TypeIndex
                                : (int?)null;
            int?CommonValueTypeNumber =
                CommonValueTM != null ?
                CommonValueTM.TypeIndex
                                : (int?)null;


            this.ChannelEnterDictionary(ref channelInfos);

            // TODO: from here, separate generic dictionaries from object dict.

            Type CommonKeyTMType =
                CommonKeyTM != null ? CommonKeyTM.l2TypeManager.L1TypeManager.type : null;
            Type CommonValueTMType =
                CommonValueTM != null ? CommonValueTM.l2TypeManager.L1TypeManager.type : null;

            foreach (object _item in AsIDictionary)
            {
                object Key, Value;
                if (_item is DictionaryEntry)
                {
                    DictionaryEntry item = (DictionaryEntry)_item;
                    Key   = item.Key;
                    Value = item.Value;
                }
                else
                if (_item is KeyValuePair <object, object> )
                {
                    KeyValuePair <object, object> item = (KeyValuePair <object, object>)_item;
                    Key   = item.Key;
                    Value = item.Value;
                }
                else
                {
                    throw new Exception();
                }


                // We simply write the key and the value, with no decoration.

                if (Key != null)
                {
                    Type itemKeyType = Key.GetType();

                    L3TypeManager itemKeyTm =
                        itemKeyType != CommonKeyTMType?
                        this.l3typeManagerCollection.GetTypeManager(itemKeyType, this, true, false)                         // Items can have different types, even if all items inherit the same type.
                            : CommonKeyTM;

                    int  ItemKeyTypeNumber = itemKeyTm.TypeIndex;
                    bool WriteTypeNumber   = (ItemKeyTypeNumber != CommonKeyTypeNumber);                   // We write the type index only if it is different from the common type index.

                    this.AddAnObject(ref channelInfos, Key, null, ItemKeyTypeNumber, itemKeyTm, false, WriteTypeNumber);
                }
                else
                {
                    // We add an empty element. If not, the collection count would be wrong.
                    this.ChannelAddNull(
                        ref channelInfos
                        );
                }

                if (Value != null)
                {
                    Type itemValueType = Value.GetType();

                    L3TypeManager itemValueTm =
                        itemValueType != CommonValueTMType?
                        this.l3typeManagerCollection.GetTypeManager(itemValueType, this, true, false)                         // Items can have different types, even if all items inherit the same type.
                            : CommonValueTM;

                    int  ItemValueTypeNumber = itemValueTm.TypeIndex;
                    bool WriteTypeNumber     = (ItemValueTypeNumber != CommonValueTypeNumber);                 // We write the type index only if it is different from the common type index.

                    this.AddAnObject(ref channelInfos, Value, null, ItemValueTypeNumber, itemValueTm, false, WriteTypeNumber);
                }
                else
                {
                    // We add an empty element. If not, the collection count would be wrong.
                    this.ChannelAddNull(
                        ref channelInfos
                        );
                }
            }
            this.ChannelExitDictionary(ref channelInfos);
        }
Beispiel #23
0
 void addAllStructs <T>(IEnumerable <T> list, ref ChannelInfos channelInfos, int TypeNumber, L3TypeManager tm)
 {
     T[] array = list as T[];
     if (array != null)
     {
         int size = array.Length;
         for (int i = 0; i < size; i++)
         {
             this.AddAnObject(ref channelInfos, array[i], null, TypeNumber, tm, false, false);
         }
     }
     else
     {
         var enumerator = list.GetEnumerator();
         while (enumerator.MoveNext())
         {
             var item = enumerator.Current;
             this.AddAnObject(ref channelInfos, item, null, TypeNumber, tm, false, false);
         }
     }
 }
		internal abstract Object GetSimpleValueInElement(L3TypeManager typeManager);
        Object _LookForObjectAndManagesChannels(
            L3TypeManager WantedType,
            object AlreadyInstanciatedCollectionOrDictionary, // For inner collection or dictionary.
            long?NumberOfElements,                            // For inner collection or dictionary.
            bool AddToTheInstances)
        {
            Element e = new Element();

            {
                bool found =
                    this.GetNextElementAs(ref e, true, null, WantedType, false, false);

                if (!found)
                {
                    this.DataEndMarkHasBeenPassed = true;
                    return(DeserializationTerminated);
                }
            }

            switch (e.ElementType)
            {
            case ElementTypes.TypesChannelSection:
                // Deserialize a type descriptor and add it to the type manager collection:
            {
                SerializationTypeDescriptor td =
                    (SerializationTypeDescriptor)this.LookForObjectAndManagesChannels(
                        this.TypeDescriptorTypeManager, null, null, false);
                this.typeManagerCollection.AddNewType(td);
                this.PassClosingTag(ElementTypes.TypesChannelSection);
                return(this.LookForObjectAndManagesChannels(WantedType
                                                            , AlreadyInstanciatedCollectionOrDictionary
                                                            , NumberOfElements
                                                            , false
                                                            )); // look for next element.
            }

            case ElementTypes.InstancesChannelSection:
                // Deserialize an object and add it to the root of the instances channel:
            {
                object instance = this.LookForObjectAndManagesChannels(null
                                                                       , null
                                                                       , null
                                                                       , true
                                                                       );
                this.PassClosingTag(ElementTypes.InstancesChannelSection);
                object obj = this.LookForObjectAndManagesChannels(WantedType
                                                                  , AlreadyInstanciatedCollectionOrDictionary
                                                                  , NumberOfElements
                                                                  , false
                                                                  ); // look for next element.

                if (obj == DeserializationTerminated)
                {
                    return(instance);
                }
                return(obj);
            }

            case ElementTypes.SubBranch:     // Deserializes a structured object:
                return(this.DeserializeSubBranch(e, WantedType, AlreadyInstanciatedCollectionOrDictionary, AddToTheInstances));

            case ElementTypes.PrimitiveValue:
            {
                Object obj;
                bool   closeTagAlreadyPassed = false;
                {
                    L3TypeManager t =
                        e.typeIndexIsKnown ?
                        this.typeManagerCollection.GetTypeManager(e.typeIndex)
                            : WantedType;

                    // TODO: set GetSimpleValueInElement as generic and write a 'switch' here. Beware to avoid double switch.

                    obj = this.GetSimpleValueInElement(
                        t);
                    if (obj == DeserializationFormatter.NoValue)
                    {
                        // specific to xml. In xml, we have <p></p> for a string.Empty .
#if DEBUG
                        if (this.GetType() != typeof(XmlDeserializationFormatter))
                        {
                            throw new Exception();
                        }
#endif
                        closeTagAlreadyPassed = true;
                        obj = string.Empty;
                    }
                }


                if (AddToTheInstances)
                {
#if DEBUG
                    if (obj.GetType() != typeof(string))
                    {
                        Debugger.Break();
                    }
#endif
                    this.instancesChannel.AddInstance(obj);
                }

                if (!closeTagAlreadyPassed)
                {
                    this.PassClosingTag(ElementTypes.PrimitiveValue);
                }

                return(obj);
            }

            case ElementTypes.Reference:
            {
                Object obj;

#if DEBUG
                if (AddToTheInstances)
                {
                    Debugger.Break();
                }
#endif
                obj = this.instancesChannel.GetInstance(e.InstanceIndex.Value);

                if (e.NeedsAnEndElement)
                {
#if DEBUG
                    // In xml, <e/> elements can be closed in the same tag.
                    if (this.GetType() == typeof(XmlDeserializationFormatter))
                    {
                        throw new Exception();
                    }
#endif
                    this.PassClosingTag(ElementTypes.Reference);
                }

                return(obj);
            }

            case ElementTypes.Null:
            {
                Object obj = null;

                if (e.NeedsAnEndElement)
                {
#if DEBUG
                    // In xml, <e/> elements can be closed in the same tag.
                    if (this.GetType() == typeof(XmlDeserializationFormatter))
                    {
                        throw new Exception();
                    }
#endif
                    this.PassClosingTag(ElementTypes.Null);
                }

                return(obj);
            }

            case ElementTypes.Collection:
                return(DeserializeCollection(AlreadyInstanciatedCollectionOrDictionary, NumberOfElements.Value, WantedType, e));

            case ElementTypes.Dictionary:
                return(DeserializeDictionary(AlreadyInstanciatedCollectionOrDictionary, NumberOfElements.Value, WantedType, e));

            default:
                byte code = (byte)e.ElementType;
                throw new NotImplementedException(code.ToString());
            }
            throw new NotImplementedException();
        }
        // --------------------------------------------------

        Object DeserializeCollection(
            object collection,
            long NumberOfElements,
            L3TypeManager WantedType,
            Element e
            )
        {
#if false//DEBUG
            //if (collection.GetType().Name == "RelationsDHéritage")
            if (WantedType.l2TypeManager.L1TypeManager.Name == "List<DéclarationStructurée>")
            {
                Debugger.Break();
            }
#endif

#if DEBUG
            if (collection == null || WantedType == null)
            {
                Debugger.Break();
            }
#endif
            IList list             = collection as IList;
            bool  listIsNotIndexed = list == null;
            if (listIsNotIndexed)
            {
                Type ItemType;
                list = Tools.GetIListBoxer(collection as IEnumerable, out ItemType);
            }

            Array array     = collection as Array;
            bool  is1DArray = array != null && array.Rank == 1;
#if DEBUG
            if (array != null && array.Rank != 1)
            {
                throw new Exception(
                          ErrorMessages.GetText(1));//"This version of UniversalSerializer can not manage multi-dimentionnal arrays."
            }
#endif
            L3TypeManager itemsType = WantedType.CollectionItemsTypeManager;// Manager.Value;
#if false
            if (itemsType == null)
            {
                Debugger.Break();
            }
#endif

            for (int i = 0; i < NumberOfElements; i++)
            {
                var item = this.LookForObjectAndManagesChannels(
                    itemsType
                    , null
                    , null
                    , false
                    );

                var notReady = item as InstancesChannel.InstanceNotReadyAndListOfNeeds;

                if (is1DArray)
                {
                    if (notReady == null)
                    {
                        list[i] = item;
                    }
                    else
                    {
                        var iCopy    = i;    // tells C# to not use a closure for the following lambda.
                        var listCopy = list; // tells C# to not use a closure for the following lambda.
                        notReady.Setters.Add((o) => listCopy[iCopy] = o);
                    }
                }
                else
                if (notReady == null)
                {
#if NET3_5
                    // .NET 3.5 can not do IList.Add(null) on a List<T>. This is a workaround.
                    if (item == null && WantedType != null && WantedType.CollectionItemsTypeManager.l2TypeManager.L1TypeManager.IsNullable)
                    {
                        var m = WantedType.ItemAdder.Value;
                        if (m != null)
                        {
                            m(list, null);
                        }
                        else
                        {
                            list.Add(item);
                        }
                    }
                    else
                    {
                        list.Add(item);
                    }
#else
                    list.Add(item);
#endif
                }
                else
                {
                    if (listIsNotIndexed)
                    {
                        throw new NotSupportedException(
                                  string.Format(ErrorMessages.GetText(22), // "Type {0} has a circular type in its constructor parameters in a form that is not supported."
                                                Tools.GetName(itemsType.l2TypeManager.L1TypeManager.type)));
                    }
                    list.Add(itemsType.l2TypeManager.DefaultValue); // reserve space, to preserve right indexes.
                    var listCopy = list;                            // tells C# to not use a closure for the following lambda.
                    var iCopy    = i;                               // tells C# to not use a closure for the following lambda.
                    notReady.Setters.Add((o) => listCopy[iCopy] = o);
                }
            }
            if (e.NeedsAnEndElement)
            {
                this.PassClosingTag(ElementTypes.Collection);
            }

            return(collection);
        }
		internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
		{
#if DEBUG
			if (typeManager==null)
				throw new Exception();
#endif

			return this.ReadPrimitiveObjectFromBinaryStream(this.binaryReader, typeManager, this.parameters.CompressIntsAs7Bits);
		}
Beispiel #28
0
 /// <summary>
 /// If the right element is not found, an exception occures.
 /// Optionnaly, We can accept a channel section.
 /// </summary>
 internal abstract bool GetNextElementAs(
     ref Element e,
     bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement);
        internal override bool GetNextElementAs(
            ref Element e,
            bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement)
        {
            int?SupposedTypeNumber = SupposedType != null ? SupposedType.TypeIndex : (int?)null;

            if (!this.GetNextXmlPart())
            {
                if (NeedsThisElement)
                {
                    throw new Exception();
                }
                else
                {
                    return(false);                    // end of document.
                }
            }
            if (this.xmlReader.Name == XmlSerializationFormatter.DataEndMarkTag)
            {
                return(false);                // end of document.
            }
            ElementTypes?et2 = this.GetElementType();
            if (et2 == null)
            {
#if DEBUG
                if (this.xmlReader.NodeType != XmlNodeType.EndElement && this.xmlReader.Name != "data")
                {
                    Debugger.Break();
                }
#endif
                return(false);
            }
            ElementTypes et = et2.Value;

            if (WantClosingElement && this.xmlReader.NodeType == XmlNodeType.Element)
            {
                if (NeedsThisElement)
                {
                    throw new Exception();
                }
                else
                {
                    return(false);
                }
            }

#if DEBUG
            if (!AcceptChannelSection &&
                !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
            {
                throw new Exception();
            }


            // Checks name correspondance:
            string name = this.xmlReader.GetAttribute(XmlAttributeName.Name);
            if (Name != null && name != null && name != Name)
            {
                throw new Exception();
            }
#endif

            string typeNumber = this.xmlReader.GetAttribute(XmlAttributeName.TypeNumber);
#if DEBUG
            // Checks type correspondance:
            if (typeNumber != null && typeNumber != string.Empty && SupposedTypeNumber != null)
            {
                int foundTypeNumber = int.Parse(typeNumber);
                if (foundTypeNumber != SupposedTypeNumber.Value)
                {
                    var found    = this.typeManagerCollection.GetTypeManager(foundTypeNumber);
                    var foundGtd = found.l2TypeManager.L1TypeManager;
                    if (!foundGtd.type.Is(typeof(ITypeContainer)))
                    {
                        var supposed    = this.typeManagerCollection.GetTypeManager(SupposedTypeNumber.Value);
                        var supposedGtd = supposed.l2TypeManager.L1TypeManager;
                        if (!foundGtd.type.Is(supposedGtd.type))
                        {
                            if (!supposedGtd.IsNullable || supposedGtd.type.GetGenericArguments().Length == 0 || !foundGtd.type.Is(supposedGtd.type.GetGenericArguments()[0]))
                            {
                                throw new Exception();
                            }
                        }
                    }
                }
            }
#endif
            int?tn =
                typeNumber != null ? (
                    int.Parse(typeNumber))
                                : SupposedTypeNumber;

            string inum        = this.xmlReader.GetAttribute(XmlAttributeName.InstanceIndex);
            int?InstanceNumber =
                inum != null?
                int.Parse(inum)
                    : (int?)null;

            string noe            = this.xmlReader.GetAttribute(XmlAttributeName.NumberOfElements);
            long?numberOfElements =
                noe != null?
                long.Parse(noe)
                    : (long?)null;

            e.ContainsAValue = !this.xmlReader.IsEmptyElement;
            e.ElementType    = et;
            e.InstanceIndex  = InstanceNumber;
            e.IsAClosingTag  = this.xmlReader.NodeType == XmlNodeType.EndElement;
#if DEBUG
            e.Name = name != null ? name : Name;
#endif
            e.NeedsAnEndElement = !this.xmlReader.IsEmptyElement;
            e.NumberOfElements  = numberOfElements;
            if (tn != null)
            {
                e.typeIndex        = tn.Value;
                e.typeIndexIsKnown = true;
            }

            return(true);
        }
Beispiel #30
0
        // TODO: write a generic method for each Primitive type, in order to avoid boxing to object.
        internal static Object TranscodeStringToPrimitiveObject(string s, L3TypeManager typeManager)
        {
            TypeCode tc = (TypeCode)typeManager.TypeIndex;

#if DEBUG
            if ((int)tc < (int)TypeCode.Boolean)
            {
                throw new ArgumentException(ErrorMessages.GetText(9));                //"data is not a Primitive type");
            }
#endif
            switch (tc)
            {
            case TypeCode.Boolean:
                return(Boolean.Parse(s));

            case TypeCode.Byte:
                return(Byte.Parse(s));

            case TypeCode.Char:
#if SILVERLIGHT || PORTABLE
                return(s[0]);
#else
                return(Char.Parse(s));
#endif
            case TypeCode.DateTime:
                return(Tools.DateTimeFromTicksAndKind(ulong.Parse(s)));

            case TypeCode.Decimal:
                return(Decimal.Parse(s, Tools.EnUSCulture));

            case TypeCode.Double:
                return(Double.Parse(s, Tools.EnUSCulture));

            case TypeCode.Int16:
                return(Int16.Parse(s));

            case TypeCode.Int32:
                return(Int32.Parse(s));

            case TypeCode.Int64:
                return(Int64.Parse(s));

            case TypeCode.SByte:
                return(SByte.Parse(s));

            case TypeCode.Single:
                return(Single.Parse(s, Tools.EnUSCulture));

            case TypeCode.String:
                return(s);

            case TypeCode.UInt16:
                return(UInt16.Parse(s));

            case TypeCode.UInt32:
                return(UInt32.Parse(s));

            case TypeCode.UInt64:
                return(UInt64.Parse(s));

            default:
                throw new Exception();
            }
        }
        // --------------------------------------------------

        Object DeserializeSubBranch(
            Element e, L3TypeManager WantedType,
            object AlreadyInstanciatedCollectionOrDictionary, // For inner collection or dictionary.
            bool AddToTheInstances)
        {
            L3TypeManager typeManager =
                e.typeIndexIsKnown && (WantedType == null || (WantedType != null && e.typeIndex != WantedType.TypeIndex)) ?
                this.typeManagerCollection.GetTypeManager(e.typeIndex)
                : WantedType;

            // TODO: try to dynamically build a method that deserializes this particular type by this formatter.

            // Two different ways: with a default constructor or with a parametric constructor.
            // A parametric constructor needs to deserialize fields and properties first.

            Object obj = AlreadyInstanciatedCollectionOrDictionary;

#if DEBUG
            if (AlreadyInstanciatedCollectionOrDictionary != null && AddToTheInstances)
            {
                Debugger.Break();
            }
#endif

            if (obj == null)
            {
                obj = typeManager.l2TypeManager.ConstructNewObjectAndSetMembers(typeManager, this, AddToTheInstances, e.NumberOfElements);
            }

            #region Now deserializes the inner collection
            if (typeManager.l2TypeManager.L1TypeManager.IsAnObjectIEnumerable)
            {
                if (AlreadyInstanciatedCollectionOrDictionary == null)
                {
#if DEBUG
                    if (e.NumberOfElements == null)
                    {
                        Debugger.Break();
                    }
#endif

#if DEBUG
                    IEnumerable collection = (IEnumerable)
#endif
                    this.LookForObjectAndManagesChannels(
                        typeManager
                        , obj
                        , e.NumberOfElements
                        , false
                        );
                }
            }
            #endregion Now deserializes the inner collection


            #region Now deserializes the inner dictionary
            if (typeManager.l2TypeManager.L1TypeManager.IsADictionary)
            {
                if (AlreadyInstanciatedCollectionOrDictionary == null)
                {
#if DEBUG
                    if (e.NumberOfElements == null)
                    {
                        Debugger.Break();
                    }
#endif

#if DEBUG
                    IEnumerable dictionary = (IEnumerable)
#endif
                    this.LookForObjectAndManagesChannels(
                        typeManager
                        , obj
                        , e.NumberOfElements
                        , false
                        );
                }
            }
            #endregion Now deserializes the inner dictionary

            this.PassClosingTag(ElementTypes.SubBranch);
            return(obj);
        }
		internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
		{
			if (!GetNextXmlPart())
				throw new Exception();

			if (this.xmlReader.NodeType == XmlNodeType.EndElement)
			{
#if DEBUG
				if (typeManager.l2TypeManager.L1TypeManager.type != typeof(string))
					throw new Exception();
#endif
				return DeserializationFormatter.NoValue;
			}

#if DEBUG
			if (this.xmlReader.NodeType != XmlNodeType.Text)
				throw new Exception();
#endif
			var rawValue = this.xmlReader.Value;
			return DeserializationFormatter.TranscodeStringToPrimitiveObject(rawValue, typeManager);
		}
        // --------------------------------------------------

        Object DeserializeDictionary(
            object dictionary,
            long NumberOfElements,
            L3TypeManager WantedType,
            Element e
            )
        {
#if DEBUG
            if (dictionary == null || WantedType == null)
            {
                Debugger.Break();
            }
#endif
            IDictionary dict = Tools.GenericIDictionaryBoxer <int, int> .CreateFromGenericIDictionary(dictionary, WantedType);

            L3TypeManager keysType   = WantedType.DictionaryKeysTypeManager;   // can be null, for not-generic dictionaries.
            L3TypeManager ValuesType = WantedType.DictionaryValuesTypeManager; // can be null, for not-generic dictionaries.

            for (int i = 0; i < NumberOfElements; i++)
            {
                var key   = this.LookForObjectAndManagesChannels(keysType, null, null, false);
                var Value = this.LookForObjectAndManagesChannels(ValuesType, null, null, false);

                var keyAsNotReady   = key as InstancesChannel.InstanceNotReadyAndListOfNeeds;
                var valueAsNotReady = Value as InstancesChannel.InstanceNotReadyAndListOfNeeds;

                if (keyAsNotReady == null && valueAsNotReady == null)
                {
                    dict.Add(key, Value);
                }
                else
                {
                    var dictCopy = dict; // tells C# to not use a closure for the following lambdas.

                    if (keyAsNotReady != null && valueAsNotReady != null)
                    {
                        // TODO: implement (how?)

                        string typeMsg = "[ unknown ]";
                        if (ValuesType != null && keysType != null)
                        {
                            typeMsg =
                                "[ " + Tools.GetName(keysType.l2TypeManager.L1TypeManager.type) + " or " +
                                Tools.GetName(ValuesType.l2TypeManager.L1TypeManager.type) + " ]";
                        }
                        else
                        if (WantedType != null)
                        {
                            if (WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments != null)
                            {
                                if (WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments[0] == WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments[1])
                                {
                                    typeMsg = Tools.GetName(WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments[0]);
                                }
                                else
                                {
                                    typeMsg =
                                        "[ " +
                                        Tools.GetName(WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments[0])
                                        + " or " +
                                        Tools.GetName(WantedType.l2TypeManager.L1TypeManager.AsGenericIDictionaryGenericArguments[1])
                                        + " ]";
                                }
                            }
                        }
                        throw new NotSupportedException(
                                  string.Format(ErrorMessages.GetText(22), // "Type {0} has a circular type in its constructor parameters in a form that is not supported."
                                                typeMsg));
                    }
                    else
                    if (keyAsNotReady != null)
                    {
                        var ValueCopy = Value;     // tells C# to not use a closure for the following lambda.
                        keyAsNotReady.Setters.Add((o) => dictCopy.Add(o, ValueCopy));
                    }
                    else
                    {
                        var keyCopy = key;     // tells C# to not use a closure for the following lambda.
                        valueAsNotReady.Setters.Add((o) => dictCopy.Add(keyCopy, o));
                    }
                }
            }
            if (e.NeedsAnEndElement)
            {
                this.PassClosingTag(ElementTypes.Dictionary);
            }

            return(dictionary);
        }
		// ------------------------------

		internal override Object GetSimpleValueInElement(L3TypeManager typeManager)
		{
			if (!GetNextJSONPart())
				throw new Exception();
			if (this._JSONReader.NodeType == XmlNodeType.EndElement)
			{ // empty 'e' element.
				this.WeAlreadyObtainedJSONPart = true;
				return null;
			}
#if DEBUG
			if (this._JSONReader.NodeType != XmlNodeType.Element || this._JSONReader.Name != "a:item")
				throw new Exception();
#endif

			{
				if (!GetNextJSONPart())
					throw new Exception();
#if DEBUG
				if (this._JSONReader.NodeType != XmlNodeType.Text || this._JSONReader.Name != string.Empty)
					throw new Exception();
#endif
			}

			string rawValue;
			{
				// JsonReaderWriterFactory is very special: it splits string when it encounters a special character.
				// Therfore, we need to concatenate this parts.

				var Texts = new StringBuilder(this._JSONReader.Value);
				while (GetNextJSONPart())
				{
					if (this._JSONReader.NodeType != XmlNodeType.Text)
					{
						this.WeAlreadyObtainedJSONPart = true;
						break;
					}
					Texts.Append(this._JSONReader.Value);
				}
				rawValue = Texts.ToString();
			}

			{ // passes EndElement:
				if (!GetNextJSONPart())
					throw new Exception();
#if DEBUG
				if (this._JSONReader.NodeType != XmlNodeType.EndElement || this._JSONReader.Name != "a:item")
					throw new Exception();
#endif
			}

			return DeserializationFormatter.TranscodeStringToPrimitiveObject(rawValue, typeManager);
		}
		// TODO: write a generic method for each Primitive type, in order to avoid boxing to object.
		internal Object ReadPrimitiveObjectFromBinaryStream(FileTools.BinaryReader2 binaryReader, L3TypeManager typeManager, bool CompressIntsAs7Bits)
		{
			TypeCode tc = (TypeCode)typeManager.TypeIndex;
#if DEBUG
			if ((int)tc < (int)TypeCode.Boolean)
				throw new ArgumentException("data is not a Primitive type");
#endif
			switch (tc)
			{
				case TypeCode.Boolean:
					return binaryReader.ReadBoolean();
				case TypeCode.Byte:
					return binaryReader.ReadByte();
				case TypeCode.Char:
					return binaryReader.ReadChar();
				case TypeCode.DateTime:
					return new DateTime(binaryReader.ReadInt64());
				case TypeCode.Decimal:
					return binaryReader.ReadDecimal();
				case TypeCode.Double:
					return binaryReader.ReadDouble();
				case TypeCode.SByte:
					return binaryReader.ReadSByte();
				case TypeCode.Single:
					return binaryReader.ReadSingle();
				case TypeCode.String:
					return binaryReader.ReadString();

				case TypeCode.Int16:
					if (CompressIntsAs7Bits)
						return binaryReader.ReadSpecial7BitEncodedShort();
					else
						return binaryReader.ReadInt16();
				case TypeCode.Int32:
					if (CompressIntsAs7Bits)
						return binaryReader.ReadSpecial7BitEncodedInt();
					else
						return binaryReader.ReadInt32();
				case TypeCode.Int64:
					if (CompressIntsAs7Bits)
						return binaryReader.ReadSpecial7BitEncodedLong();
					else
						return binaryReader.ReadInt64();
				case TypeCode.UInt16:
					if (CompressIntsAs7Bits)
						return binaryReader.Read7BitEncodedUShort();
					else
						return binaryReader.ReadUInt16();
				case TypeCode.UInt32:
					if (CompressIntsAs7Bits)
						return binaryReader.Read7BitEncodedUInt();
					else
						return binaryReader.ReadUInt32();
				case TypeCode.UInt64:
					if (CompressIntsAs7Bits)
						return binaryReader.Read7BitEncodedULong();
					else
						return binaryReader.ReadUInt64();

				default:
#if DEBUG
					throw new Exception();
#else
					return null;
#endif
			}
		}
		[System.Runtime.CompilerServices.MethodImpl((System.Runtime.CompilerServices.MethodImplOptions)256)] // AggressiveInlining
		internal override bool GetNextElementAs(
			ref Element e,
			bool AcceptChannelSection, string Name, L3TypeManager SupposedType, bool NeedsThisElement, bool WantClosingElement)
		{
			bool SupposedTypeNumberIsKnown = SupposedType != null;

			// There is no tag for value primitive types:
			if (SupposedTypeNumberIsKnown
				&& SupposedType.TypeIndex < (int)TypeCode.String
				&& SupposedType.TypeIndex >= (int)TypeCode.Boolean)
			{
				e.ContainsAValue = true;
				e.ElementType = ElementTypes.PrimitiveValue;
				e.IsAClosingTag = true;
				e.typeIndex = SupposedType.TypeIndex;
				e.typeIndexIsKnown = true;
				return true;
			}

			// There is no tag for structures:
			if (SupposedTypeNumberIsKnown
				&& SupposedType.TypeIndex != (int)TypeCode.Object
				&& SupposedType.l2TypeManager.L1TypeManager.IsStructure
				&& (SupposedType.l2TypeManager.Container==null)
				&& !SupposedType.l2TypeManager.L1TypeManager.IsNullable)
			{
				e.ContainsAValue = false;
				e.ElementType = ElementTypes.SubBranch;
				e.IsAClosingTag = true;
				e.typeIndex = SupposedType.TypeIndex;
				e.typeIndexIsKnown = true;
				return true;
			}



			// 1) Element code : byte
			int b = this.binaryReader.BaseStream.ReadByte(); // Unlike this.binaryReader.ReadByte(), this function does not cause an exception (exceptions can prevent method inlining).

			if (b < 0)
#if DEBUG
				throw new EndOfStreamException();
#else
				return false; // end of file.
#endif
			byte elementCode = unchecked((byte)b);
			if (elementCode==BinarySerializationFormatter.DataEndMarkCode)
				return false; // end of file.

			ElementTypes et = (ElementTypes)(elementCode & (byte)BinaryElementCode.BitMask);

#if DEBUG
			if (!AcceptChannelSection
						&& !(et == ElementTypes.InstancesChannelSection || et == ElementTypes.TypesChannelSection))
				throw new Exception();
#endif

			// 2) typeNumber : 7 bit-compressed int
			bool HasTypeNumber = (elementCode & (byte)BinaryAttributeCode.HasATypeNumber) != 0;

#if DEBUG
			if (!SupposedTypeNumberIsKnown && !HasTypeNumber
				&& (elementCode == (byte)BinaryElementCode.PrimitiveValue || elementCode == (byte)BinaryElementCode.SubBranch))
				throw new Exception();
#endif

			int typeNumber =
				HasTypeNumber ?
				this.binaryReader.Read7BitEncodedInt()
				: (SupposedTypeNumberIsKnown ? SupposedType.TypeIndex : 0);

			// 3) Reference InstanceIndex : 7 bit-compressed int
			int? InstanceNumber =
				et == ElementTypes.Reference ?
				this.binaryReader.Read7BitEncodedInt()
				: (int?)null;

			// 4) NumberOfElements : 7 bit-compressed long			
			bool HasANumberOfElements = (elementCode & (byte)BinaryAttributeCode.HasANumberOfElements) != 0;
			long? numberOfElements =
				HasANumberOfElements ?
				this.binaryReader.Read7BitEncodedLong()
				: (long?)null;
#if DEBUG
			if (HasANumberOfElements && et != ElementTypes.SubBranch)
				Debugger.Break();
#endif

			e.ElementType = et;
#if DEBUG
 e.Name= Name;
#endif
			e.typeIndexIsKnown = SupposedTypeNumberIsKnown | HasTypeNumber;
			e.typeIndex = typeNumber;
			e.InstanceIndex = InstanceNumber;
			e.IsAClosingTag = true;
			e.NumberOfElements = numberOfElements;
			e.ContainsAValue = et == ElementTypes.PrimitiveValue;
			return true;
		}
        internal object ConstructAndSetMembers <T>(
            L3TypeManager l3TypeManager,
            bool AddToTheInstances, long?NumberOfElements)
        {
#if false//DEBUG
            if (l3TypeManager.l2TypeManager.L1TypeManager.Name == "CircularInstancesInAListAndParametricConstructor")
            {
                Debugger.Break();
            }
#endif

            L2GenericTypeManager <T> typeManager = l3TypeManager.l2TypeManager as L2GenericTypeManager <T>;

            T   obj;
            var gtd = typeManager.L1TypeManager;

            if (gtd.type.IsArray)
            {
                object array = Array.CreateInstance(typeManager.CollectionItemsTypeManager.L1TypeManager.type,
#if SILVERLIGHT || PORTABLE || WINDOWS_UWP
                                                    checked ((int)NumberOfElements.Value)
#else
                                                    NumberOfElements.Value
#endif
                                                    );
                if (AddToTheInstances)
                {
                    this.instancesChannel.AddInstance(array); // Adds the instance before deserializing inner data. Because of possible circular types.
                }
                return(array);
            }
            else
            if (typeManager.DefaultConstructor != null)
            {
                #region Build from a default (no-param) constructor

                // creates an instance (or a value if it is a structure):
#if SILVERLIGHT
                if (typeManager.L1TypeManager.type.IsEnum)
                {
                    obj = default(T);
                }
                else
#endif
                obj = (T)typeManager.DefaultConstructor();

                if (AddToTheInstances)
                {
                    this.instancesChannel.AddInstance(obj);     // Add the instance before deserializing inner data.
                }
                if (typeManager.SelectedFields != null)
                {
                    typeManager.SetFieldValues(ref obj,
                                               GetFieldValues(l3TypeManager));
                }

                if (typeManager.SelectedProperties != null)
                {
                    typeManager.SetPropertyValues(ref obj,
                                                  GetPropertyValues(l3TypeManager));
                }

                #endregion Build from a default (no-param) constructor
            }
            else
            if (typeManager.parametricConstructorDescriptor != null)
            #region Build from a parametric constructor
            {
                int instanceIndex = 0;
                if (AddToTheInstances)
                {
                    instanceIndex = this.instancesChannel.ReserveSpaceForInstance();         // reserves site.
                }


                object[] fieldValues =
                    (typeManager.SelectedFields != null) ?
                    GetFieldValues(l3TypeManager)
                                : new object[0];
                for (int i = 0; i < fieldValues.Length; i++)
                {
                    var nr = fieldValues[i] as InstancesChannel.InstanceNotReadyAndListOfNeeds;
                    if (nr != null)
                    {
                        var iCopy = i;         // tells C# to not use a closure for the following lambda.
                        nr.Setters.Add((o) => fieldValues[iCopy] = o);
                    }
                }

                object[] propValues =
                    (typeManager.SelectedProperties != null) ?
                    GetPropertyValues(l3TypeManager)
                                : new object[0];
                for (int i = 0; i < propValues.Length; i++)
                {
                    var nr = propValues[i] as InstancesChannel.InstanceNotReadyAndListOfNeeds;
                    if (nr != null)
                    {
                        var iCopy = i;         // tells C# to not use a closure for the following lambda.
                        nr.Setters.Add((o) => propValues[iCopy] = o);
                    }
                }

#if false // Future use, when the parameter indexes will be on both fields and properties.
                object[] fieldsAndProps = new object[fieldValues.Length + propValues.Length];
                fieldValues.CopyTo(fieldsAndProps, 0);
                propValues.CopyTo(fieldsAndProps, fieldValues.Length);
#endif
                // TODO: check if the deserialized ParametricConstructorDescriptor is the same as the TypeManager's one.

                int      nbPars     = typeManager.parametricConstructorDescriptor.ParameterFields.Length;
                object[] parameters = new object[nbPars];
                if (nbPars > 0 && typeManager.ParametricConstructorFieldParameterIndexes == null)
                {
                    throw new Exception(ErrorMessages.GetText(19));         // "Type {0} can not be deserialized because of 1) an error in its Container and 2) a refused private field."
                }
                for (int ipars = 0; ipars < nbPars; ipars++)
                {
                    parameters[ipars] = fieldValues[typeManager.ParametricConstructorFieldParameterIndexes[ipars]];
                }

                // I do not use a Linq Expression compiled constructor because it takes a lot of time to be produced.
                // A reflection constructor call is slower but it has no creation time.
                try
                {
                    obj = (T)typeManager.parametricConstructorDescriptor.constructorInfo.Invoke(parameters);
                }
                catch (Exception e)
                {
                    string msg = string.Format(
                        ErrorMessages.GetText(11),        //"Construction (instanciation) of type \"{0}\" caused an error: {1}."
                        typeof(T).FullName, e.Message);
                    for (int ip = 0; ip < parameters.Length; ip++)
                    {
                        var p = parameters[ip];
                        if (p != null)
                        {
                            msg += string.Format("\n\tParameter #{0} is type \"{1}\".", ip.ToString(), p.GetType().FullName);
                        }
                    }
                    Log.WriteLine(msg);
                    throw new Exception(msg, e);
                }

                if (AddToTheInstances)
                {
                    this.instancesChannel.SetInstance(instanceIndex, obj);
                }

                if (fieldValues.Length > 0)
                {
                    typeManager.SetFieldValues(ref obj, fieldValues);
                }

                if (propValues.Length > 0)
                {
                    typeManager.SetPropertyValues(ref obj, propValues);
                }
            }
            #endregion Build from a parametric constructor
            else
            {
                string msg = string.Format(
                    ErrorMessages.GetText(12)        //"No exploitable constructor for type {0}"
                    , gtd.type.FullName);
                Log.WriteLine(msg);

                throw new Exception(msg);         // No valid constructor.
            }

            return(obj);
        }