/// <summary> /// Gets the sequence of fields to be serialized for the specified type. This sequence is retreived according to /// the field-types specified by the user. /// </summary> /// <param name="typeWrapper">The type wrapper for the type whose serializable /// fields is going to be retreived.</param> /// <returns>the sequence of fields to be serialized for the specified type</returns> private IEnumerable<MemberWrapper> GetFieldsToBeSerialized(UdtWrapper typeWrapper) { foreach (var member in typeWrapper.UnderlyingType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { char name0 = member.Name[0]; if ((Char.IsLetter(name0) || name0 == '_') && (member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field)) { if((typeWrapper.IsCollectionType || typeWrapper.IsDictionaryType)) //&& typeWrapper.IsAttributedAsNotCollection) if(ReflectionUtils.IsPartOfNetFx(member)) continue; var memInfo = new MemberWrapper(member, this); if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize)) { yield return memInfo; } } } }
/// <summary> /// Deserializes a dictionary member which also benefits from a YAXDictionary attribute /// </summary> /// <param name="o">The object to hold the deserialized value.</param> /// <param name="member">The member corresponding to the dictionary member.</param> /// <param name="xelemValue">The XML element value.</param> private void DeserializeTaggedDictionaryMember(object o, MemberWrapper member, XElement xelemValue) { object dic = DeserializeTaggedDictionaryValue(xelemValue, member.Alias, member.MemberType, member.CollectionAttributeInstance, member.DictionaryAttributeInstance); try { member.SetValue(o, dic); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } }
/// <summary> /// Deserializes the collection member. /// </summary> /// <param name="o">The object to store the retrieved value at.</param> /// <param name="member">The member of the specified object whose value we intent to retreive.</param> /// <param name="colType">Type of the collection to be retrieved.</param> /// <param name="elemValue">The value of the element stored as string.</param> /// <param name="xelemValue">The XML element value to be retreived. If the value to be retreived /// has been stored in an XML attribute, this reference is <c>null</c>.</param> private void DeserializeCollectionMember(object o, MemberWrapper member, Type colType, string elemValue, XElement xelemValue) { object colObject; if (member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially && (member.IsSerializedAsAttribute || member.IsSerializedAsValue)) { colObject = DeserializeCollectionValue(colType, new XElement("temp", elemValue), "temp", member.CollectionAttributeInstance); } else { XName memberAlias = member.Alias.OverrideNsIfEmpty(TypeNamespace); colObject = DeserializeCollectionValue(colType, xelemValue, memberAlias, member.CollectionAttributeInstance); } try { member.SetValue(o, colObject); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } }
/// <summary> /// Retreives the value of the element from the specified XML element or attribute. /// </summary> /// <param name="o">The object to store the retrieved value at.</param> /// <param name="member">The member of the specified object whose value we intent to retreive.</param> /// <param name="elemValue">The value of the element stored as string.</param> /// <param name="xelemValue">The XML element value to be retreived. If the value to be retreived /// has been stored in an XML attribute, this reference is <c>null</c>.</param> private void RetreiveElementValue(object o, MemberWrapper member, string elemValue, XElement xelemValue) { Type memberType = member.MemberType; // try to retrieve the real-type if specified if (xelemValue != null) { XAttribute realTypeAttribute = xelemValue.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, m_documentDefaultNamespace); if (realTypeAttribute != null) { Type realType = ReflectionUtils.GetTypeByName(realTypeAttribute.Value); if (realType != null) { memberType = realType; } } } if (xelemValue != null && XMLUtils.IsElementCompletelyEmpty(xelemValue) && !ReflectionUtils.IsBasicType(memberType) && !member.IsTreatedAsCollection && !member.IsTreatedAsDictionary && !AtLeastOneOfMembersExists(xelemValue, memberType)) { try { member.SetValue(o, member.DefaultValue); } catch { OnExceptionOccurred(new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue), member.TreatErrorsAs); } } else if (memberType == typeof(string)) { if (String.IsNullOrEmpty(elemValue) && xelemValue != null) { elemValue = xelemValue.IsEmpty ? null : String.Empty; } try { member.SetValue(o, elemValue); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } else if (ReflectionUtils.IsBasicType(memberType)) { object convertedObj; if (ReflectionUtils.IsNullable(memberType) && String.IsNullOrEmpty(elemValue)) { convertedObj = member.DefaultValue; } else { convertedObj = ReflectionUtils.ConvertBasicType(elemValue, memberType); } try { try { member.SetValue(o, convertedObj); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } catch (Exception ex) { if (ex is YAXException) { throw; } OnExceptionOccurred(new YAXBadlyFormedInput(member.Alias.LocalName, elemValue), member.TreatErrorsAs); try { member.SetValue(o, member.DefaultValue); } catch { OnExceptionOccurred(new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue), m_defaultExceptionType); } } } else if (member.IsTreatedAsDictionary && member.DictionaryAttributeInstance != null) { DeserializeTaggedDictionaryMember(o, member, xelemValue); } else if (member.IsTreatedAsCollection) { DeserializeCollectionMember(o, member, memberType, elemValue, xelemValue); } else { var ser = new YAXSerializer(memberType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption); ser.m_documentDefaultNamespace = m_documentDefaultNamespace; ser.SetNamespaceToOverrideEmptyNamespace( member.Namespace. IfEmptyThen(TypeNamespace). IfEmptyThenNone()); ser.IsCraetedToDeserializeANonCollectionMember = !(member.IsTreatedAsDictionary || member.IsTreatedAsCollection); if (m_desObject != null) // i.e. it is in resuming mode ser.SetDeserializationBaseObject(member.GetValue(o)); object convertedObj = ser.DeserializeBase(xelemValue); m_parsingErrors.AddRange(ser.ParsingErrors); try { member.SetValue(o, convertedObj); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } }
/// <summary> /// Checks whether at least one of the collection memebers of /// the specified collection exists. /// </summary> /// <param name="elem">The XML element to check its content.</param> /// <param name="member">The class-member corresponding to the collection for /// which we intend to check existence of its members.</param> /// <returns></returns> private bool AtLeastOneOfCollectionMembersExists(XElement elem, MemberWrapper member) { if (!((member.IsTreatedAsCollection || member.IsTreatedAsDictionary) && member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement)) throw new ArgumentException("member should be a collection serialized without containing element"); XName eachElementName = null; if (member.CollectionAttributeInstance != null) { eachElementName = StringUtils.RefineSingleElement(member.CollectionAttributeInstance.EachElementName); } if (member.DictionaryAttributeInstance != null && member.DictionaryAttributeInstance.EachPairName != null) { eachElementName = StringUtils.RefineSingleElement(member.DictionaryAttributeInstance.EachPairName); } if (eachElementName == null) { Type colItemType = ReflectionUtils.GetCollectionItemType(member.MemberType); eachElementName = StringUtils.RefineSingleElement(ReflectionUtils.GetTypeFriendlyName(colItemType)); } // return if such an element exists return (elem.Element(eachElementName.OverrideNsIfEmpty(member.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone())) != null); }
/// <summary> /// Makes the element corresponding to the member specified. /// </summary> /// <param name="insertionLocation">The insertion location.</param> /// <param name="member">The member to serialize.</param> /// <param name="elementValue">The element value.</param> /// <param name="moveDescOnly">if set to <c>true</c> specifies that only the descendants of the resulting element should be added to the parent.</param> /// <param name="alreadyAdded">if set to <c>true</c> specifies the element returned is /// already added to the parent element and should not be added once more.</param> /// <returns></returns> private XElement MakeElement(XElement insertionLocation, MemberWrapper member, object elementValue, out bool moveDescOnly, out bool alreadyAdded) { moveDescOnly = false; RegisterNamespace(member.Namespace, member.NamespacePrefix); XElement elemToAdd; if (member.IsTreatedAsDictionary) { elemToAdd = MakeDictionaryElement(insertionLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace), elementValue, member.DictionaryAttributeInstance, member.CollectionAttributeInstance); if (member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement && !elemToAdd.HasAttributes) moveDescOnly = true; alreadyAdded = elemToAdd.Parent == insertionLocation; } else if (member.IsTreatedAsCollection) { elemToAdd = MakeCollectionElement(insertionLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace), elementValue, member.CollectionAttributeInstance, member.Format); if (member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement && !elemToAdd.HasAttributes) moveDescOnly = true; alreadyAdded = elemToAdd.Parent == insertionLocation; } else { elemToAdd = MakeBaseElement(insertionLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace), elementValue, out alreadyAdded); } if (member.PreservesWhitespace) XMLUtils.AddPreserveSpaceAttribute(elemToAdd); return elemToAdd; }