// -------------------------------------------------- // -------------------------------------------------- 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); }
// ------------------------------------------------------------------------------- /// <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); }
// --------------------------------------------- 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; }
// 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 } }
internal abstract Object GetSimpleValueInElement(L3TypeManager typeManager);
// ------------------------------ /// <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); }
// ------------------------------ 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)); }
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); }
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); } }
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); } }
// --------------------------------------------- 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); }
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); } } }
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); }
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); }
// 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); }