internal override void PassPreamble() { { // we can not create the XmlReader in the formatter class constructor since this reader constructor starts to read the stream. // We need to create a new reader for each serialization. XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreProcessingInstructions = true; settings.IgnoreWhitespace = true; this.xmlReader = XmlReader.Create(this.stream, settings); } this.xmlReader.Read(); this.xmlReader.Read(); this.xmlReader.Read(); this.xmlReader.Read(); if (this.xmlReader.Value == "2.0") { this.Version = StreamFormatVersion.Version2_0; } else if (this.xmlReader.Value == "3.0") { this.Version = StreamFormatVersion.Version3_0; } else { throw new Exception(ErrorMessages.GetText(7)); // "Unknown file version." } this.xmlReader.Read(); }
/// <summary> /// Returns a TypeConverterContainer<T>. /// </summary> public ITypeContainer CreateNewContainer(object ContainedObject) { if (ContainedObject == null) { return(null); } Type type = ContainedObject.GetType(); ITypeContainer obj = null; TypeConverter tc = GetTypeConverterByCache(type); try { if (tc.CanConvertTo(TypeString) && tc.CanConvertFrom(TypeString)) { obj = CreateATypeConverterContainerGeneric(type, TypeString, tc.ConvertTo(null, Tools.EnUSCulture, ContainedObject, TypeString)); if (obj != null) { var o2 = obj as _CLRTypeConverterContainerGeneric <string>; if (o2.Serialized == null || o2.Serialized == type.FullName) { Log.WriteLine(string.Format( ErrorMessages.GetText(15) //"The type '{0}' uses {1} as TypeConverter, but it does not convert to string correctly. Please investigate or contact the type's author." , type.FullName, tc.GetType().FullName)); return(null); } } } else if (tc.CanConvertTo(TypeByteArray) && tc.CanConvertFrom(TypeByteArray)) { obj = CreateATypeConverterContainerGeneric(type, TypeByteArray, tc.ConvertTo(null, Tools.EnUSCulture, ContainedObject, TypeByteArray)); } } catch (Exception e) { Log.WriteLine(e.Message); } if (obj == null) { Log.WriteLine(string.Format( ErrorMessages.GetText(16) //"The type '{0}' uses {1} as TypeConverter, but its transcoding type is unknown. Please investigate or contact the type's author." , type.FullName, tc.GetType().FullName)); } return(obj); }
// ------------------------------ internal override void PassPreamble() { // Passes the UTF8 prefix "": if (!stream.CanSeek || (stream.CanSeek && stream.Position == 0)) { byte[] prefix = new byte[3]; int n = this.stream.Read(prefix, 0, 3); if (n != 3 || prefix[0] != 'ï' || prefix[1] != '»' || prefix[2] != '¿') { throw new FormatException("stream"); } } { // We have to build a new JSONReader on each deserialization because it just do not manage multiple json data in one stream correctly. XmlDictionaryReaderQuotas quotas = XmlDictionaryReaderQuotas.Max; this._JSONReader = JsonReaderWriterFactory.CreateJsonReader(stream, #if !SILVERLIGHT Encoding.UTF8, #endif quotas #if !SILVERLIGHT , null #endif ); } this._JSONReader.Read(); this._JSONReader.Read(); this._JSONReader.Read(); if (this._JSONReader.Value == "2.0") { this.Version = StreamFormatVersion.Version2_0; } else if (this._JSONReader.Value == "3.0") { this.Version = StreamFormatVersion.Version3_0; } else { throw new Exception(ErrorMessages.GetText(7)); // "Unknown file version." } this._JSONReader.Read(); }
static byte[] SerializeObject(object o) { using (MemoryStream stream = new MemoryStream()) { var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); try { formatter.Serialize(stream, o); } catch (Exception e) { throw new Exception(string.Format( ErrorMessages.GetText(8), //"Type '{0}' (or one of its sub-data) is not serializable by BCL's BinaryFormatter. (suggestion: try remove attribute [Serializable], or add an exploitable constructor).", o.GetType().GetName()), e); } return(stream.ToArray()); } }
// ------------------------------------------------------------------------------- internal static SerializationFormatter ChooseDefaultFormatter(Parameters parameters) { switch (parameters.SerializerFormatter) { case SerializerFormatters.BinarySerializationFormatter: return(new BinarySerializationFormatter(parameters)); #if !JSON_DISABLED case SerializerFormatters.JSONSerializationFormatter: return(new JSONSerializationFormatter(parameters)); #endif case SerializerFormatters.XmlSerializationFormatter: return(new XmlSerializationFormatter(parameters)); default: throw new ArgumentException(ErrorMessages.GetText(2)); // "Unknown CustomFormatter"); } }
internal override void PassPreamble() { string p = this.binaryReader.ReadString(); if (p == BinarySerializationFormatter.DocumentPreambleVersion2) { this.Version = StreamFormatVersion.Version2_0; } else if (p == BinarySerializationFormatter.DocumentPreambleVersion3) { this.Version = StreamFormatVersion.Version3_0; } else { throw new Exception( ErrorMessages.GetText(7)); //"Unknown file version"); } }
// ------------------------------ /// <summary> /// For each parameter, find its index in the SelectedFields, in the order of this.ParameterFields. /// </summary> /// <param name="SelectedFields">Concatenated selected public and private fields of a particular TypeManager.</param> /// <param name="CancelOnErrors">If true, an error will return null. If false, an error will throw an exception.</param> /// <returns>int[this.ParameterFields.Length]</returns> internal int[] GetParameterIndexes(FieldInfo[] SelectedFields, bool CancelOnErrors) { int[] indexes = new int[this.ParameterFields.Length]; for (int i = 0; i < this.ParameterFields.Length; i++) { var fi = ParameterFields[i]; indexes[i] = Array.IndexOf(SelectedFields, fi); if (indexes[i] < 0) { if (CancelOnErrors) { return(null); } string msg = string.Format( ErrorMessages.GetText(14) // "Type \"{0}\" can not be constructed because this parameter's type has been disallowed by a filter: Parameter's name=\"{1}\", Corresponding field's name=\"{2}\", Type=\"{3}\".\n\tSuggestion: use a filter to disallow the main type, or to allow the parameter's type." , this.constructorInfo.DeclaringType.FullName, this.constructorInfo.GetParameters()[i].Name, fi.Name, fi.FieldType.FullName); Log.WriteLine(msg); throw new Exception(msg); } } return(indexes); }
internal NoMethodsException(Type t) : base(string.Format( ErrorMessages.GetText(13) // "Type {0} has no Add() method nor [Insert() method and Count get method], we can not set its items." , t.FullName)) { }
// 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(); } }
// 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 } }
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); } }
// --------------------------------------------- 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); }
/// <summary> /// Can not cast deserialized type. /// </summary> /// <param name="DeserializedType"></param> /// <param name="WantedType"></param> public TypeMismatchException(Type DeserializedType, Type WantedType) : base(string.Format( ErrorMessages.GetText(10),// "Can not cast deserialized type \"{0}\" to wanted type \"{1}\".", DeserializedType.FullName, WantedType.FullName)) { }
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); }
// -------------------------------------------------- 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); }
// -------------------------------------------------- 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); }