/// <summary> /// Deserializes an <see cref="object"/> from the given <see cref="Stream"/> for the given <see cref="Type"/>. /// </summary> /// <param name="serializationStream">The stream to read the object from.</param> /// <param name="objectType">The type of object to create.</param> /// <returns>The deserialized object.</returns> private object Deserialize([NotNull] Stream serializationStream, Type objectType) { object deserialized; // create xml reader from stream using (XmlTextReader reader = new XmlTextReader(serializationStream)) { DeserializationCallBackList.Clear(); deserialized = InitializeObject(reader, new FormatterConverter(), objectType); } foreach (IDeserializationCallback callBack in DeserializationCallBackList) { callBack.OnDeserialization(null); } return(deserialized); }
/// <summary> /// Reads an <see cref="object"/> from the XML and initializes it. /// </summary> /// <param name="reader">The XMLTextReader to read from.</param> /// <param name="converter"> /// The <see cref="System.Runtime.Serialization.FormatterConverter">converter</see> used to parse the values from the XML. /// </param> /// <param name="objectType">The type of the object to create.</param> /// <returns>The recreated object.</returns> /// <exception cref="SerializationException"> /// <para>The stream contained an element not found in <paramref name="objectType"/>.</para> /// <para>-or</para> /// <para>A List member in the object is a <see langword="null"/>.</para> /// <para>-or-</para> /// <para>More than one member was found for an XML tag.</para> /// </exception> private object InitializeObject( [NotNull] XmlTextReader reader, [NotNull] FormatterConverter converter, Type objectType) { Type actualType; ISurrogateSelector selector1; ISerializationSurrogate serializationSurrogate; SerializationInfo info; object initializedObject = null; // check if a type attribute is present if (reader.HasAttributes) { // if so, get the type string actualTypeName = reader.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance"); Debug.Assert(actualTypeName != null); actualType = Binder.BindToType("", actualTypeName); Debug.Assert(actualType != null); } else { if (objectType == null) { throw new ArgumentNullException("objectType"); } // passed type is actual type. actualType = objectType; } // check whether a surrogate should be used, ISerializable is implemented or reflection is needed. if ((SurrogateSelector != null) && ((serializationSurrogate = SurrogateSelector.GetSurrogate(actualType, Context, out selector1)) != null)) { // use surrogate info = new SerializationInfo(actualType, converter); if (!actualType.IsPrimitive) { // create a instance of the type. initializedObject = FormatterServices.GetUninitializedObject(actualType); // read the first element reader.ReadStartElement(); while (reader.IsStartElement()) { // determine type string typeName = reader.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance"); Debug.Assert(typeName != null); Type type = Binder.BindToType("", typeName); Debug.Assert(type != null); Debug.Assert(reader.Name != null); // using ISerializable info.AddValue(reader.Name, DetermineValue(reader, converter, type)); reader.ReadEndElement(); } // use the surrogate to populate the instance initializedObject = serializationSurrogate.SetObjectData( initializedObject, info, Context, SurrogateSelector); } } else if (typeof(ISerializable).IsAssignableFrom(actualType)) { // The item implements ISerializable. Create a SerializationInfo object info = new SerializationInfo(actualType, converter); // Populate the collection PopulateSerializationInfo(reader, converter, info); // Get the specialized Serialization Constructor ConstructorInfo ctor = actualType.GetConstructor(new[] { typeof(SerializationInfo), typeof(StreamingContext) }); if (ctor == null) { throw new SerializationException("ISerializable type does not support deserialization"); } // Create the object initializedObject = ctor.Invoke(new object[] { info, Context }); } else { // The item does not implement ISerializable. Use reflection to get public // fields and properties. initializedObject = FormatterServices.GetUninitializedObject(actualType); Debug.Assert(initializedObject != null); List <MemberInfo> memberList = new List <MemberInfo>(); List <object> valuesList = new List <object>(); // read the first element. reader.ReadStartElement(); while (reader.IsStartElement()) { // Get public fields and members of this type. MemberInfo[] possibleMembers = actualType.GetMember( reader.Name, MemberTypes.Property | MemberTypes.Field, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance); if (possibleMembers.Length < 1) { throw new SerializationException( // ReSharper disable once AssignNullToNotNullAttribute string.Format(Resources.XmlFormatter_InitializeObject_ElementNotFound, reader.Name)); } if (possibleMembers.Length > 1) { throw new SerializationException( string.Format( // ReSharper disable once AssignNullToNotNullAttribute Resources.XmlFormatter_InitializeObject_MoreThanOneMemberFound, reader.Name)); } // ReSharper disable once PossibleNullReferenceException if (typeof(IList).IsAssignableFrom(possibleMembers[0].ReflectedType)) { // the type is a list, get the list from the initialized object. IList list = GetMemberValue(initializedObject, possibleMembers[0]) as IList; // ReSharper disable PossibleNullReferenceException if (list == null) { throw new SerializationException( string.Format( // ReSharper disable once AssignNullToNotNullAttribute Resources.XmlFormatter_InitializeObject_MemberListIsNull, possibleMembers[0].DeclaringType.FullName, possibleMembers[0].Name)); } // ReSharper restore PossibleNullReferenceException // read the next element reader.ReadStartElement(); while (reader.IsStartElement()) { if (!reader.IsEmptyElement) { // Initialize the object (recursive call) // ReSharper disable PossibleNullReferenceException object listItem = InitializeObject( reader, converter, possibleMembers[0].ReflectedType.GetElementType()); // ReSharper restore PossibleNullReferenceException list.Add(listItem); reader.ReadEndElement(); } else { reader.ReadStartElement(); } } } else { // determine the value. // ReSharper disable once AssignNullToNotNullAttribute object value = DetermineValue(reader, converter, possibleMembers[0].ReflectedType); memberList.Add(possibleMembers[0]); valuesList.Add(value); } } if (memberList.Count > 0) { initializedObject = FormatterServices.PopulateObjectMembers( initializedObject, memberList.ToArray(), valuesList.ToArray()); Debug.Assert(initializedObject != null); } reader.ReadEndElement(); } if ((initializedObject as IDeserializationCallback) != null) { DeserializationCallBackList.Add(initializedObject); } return(initializedObject); }