/// <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); 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) { if (xelemValue.IsEmpty) elemValue = null; else elemValue = String.Empty; } try { member.SetValue(o, elemValue); } catch { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), this.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 { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } catch (Exception ex) { if (ex is YAXException) { throw; } this.OnExceptionOccurred(new YAXBadlyFormedInput(member.Alias.LocalName, elemValue), member.TreatErrorsAs); try { member.SetValue(o, member.DefaultValue); } catch { this.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.SetNamespaceToOverrideEmptyNamespace( member.Namespace. IfEmptyThen(this.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 { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), this.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> /// 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)) { MemberWrapper memInfo = new MemberWrapper(member, this); if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize)) { yield return memInfo; } } } }
/// <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) { alreadyAdded = false; 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; } 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; } else { elemToAdd = MakeBaseElement(insertionLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace), elementValue, out alreadyAdded); } if (member.PreservesWhitespace) XMLUtils.AddPreserveSpaceAttribute(elemToAdd); return elemToAdd; }
/// <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> /// 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 { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } }
/// <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) { alreadyAdded = false; moveDescOnly = false; XElement elemToAdd; if (member.IsTreatedAsDictionary) { elemToAdd = MakeDictionaryElement(insertionLocation, member.Alias, elementValue, member.DictionaryAttributeInstance, member.CollectionAttributeInstance); if (member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement && !elemToAdd.HasAttributes) moveDescOnly = true; } else if (member.IsTreatedAsCollection) { elemToAdd = MakeCollectionElement(insertionLocation, member.Alias, elementValue, member.CollectionAttributeInstance, member.Format); if (member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement && !elemToAdd.HasAttributes) moveDescOnly = true; } else { elemToAdd = MakeBaseElement(insertionLocation, member.Alias, elementValue, out alreadyAdded); } return elemToAdd; }
/// <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"); string eachElementName = null; if (member.CollectionAttributeInstance != null) { eachElementName = member.CollectionAttributeInstance.EachElementName; } if (member.DictionaryAttributeInstance != null && member.DictionaryAttributeInstance.EachPairName != null) { eachElementName = member.DictionaryAttributeInstance.EachPairName; } if (eachElementName == null) { Type colItemType = ReflectionUtils.GetCollectionItemType(member.MemberType); eachElementName = ReflectionUtils.GetTypeFriendlyName(colItemType); } if (elem.Element(eachElementName) != null) // if such an element exists return true; else return false; }
/// <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="memberType">Type of the dictionary member.</param> /// <param name="xelemValue">The XML element value.</param> private void DeserializeTaggedDictionaryMember(object o, MemberWrapper member, Type memberType, XElement xelemValue) { // otherwise the "else if(member.IsTreatedAsCollection)" block solves the problem Type keyType, valueType; if (!ReflectionUtils.IsIDictionary(memberType, out keyType, out valueType)) { throw new Exception("elemValue must be a Dictionary"); } Type pairType = null; ReflectionUtils.IsIEnumerable(memberType, out pairType); string eachElementName = ReflectionUtils.GetTypeFriendlyName(pairType); bool isKeyAttrib = false; bool isValueAttrib = false; string keyAlias = "Key"; string valueAlias = "Value"; if (member.CollectionAttributeInstance != null) { eachElementName = member.CollectionAttributeInstance.EachElementName ?? eachElementName; } if (member.DictionaryAttributeInstance != null) { eachElementName = member.DictionaryAttributeInstance.EachPairName ?? eachElementName; if (member.DictionaryAttributeInstance.SerializeKeyAs == YAXNodeTypes.Attribute) { isKeyAttrib = ReflectionUtils.IsBasicType(keyType); } if (member.DictionaryAttributeInstance.SerializeValueAs == YAXNodeTypes.Attribute) { isValueAttrib = ReflectionUtils.IsBasicType(valueType); } keyAlias = member.DictionaryAttributeInstance.KeyName ?? keyAlias; valueAlias = member.DictionaryAttributeInstance.ValueName ?? valueAlias; } object dic = memberType.InvokeMember(string.Empty, System.Reflection.BindingFlags.CreateInstance, null, null, new object[0]); foreach (XElement childElem in xelemValue.Elements(eachElementName)) { object key = null, value = null; YAXSerializer keySer = null, valueSer = null; bool isKeyFound = VerifyDictionaryPairElements(ref keyType, ref isKeyAttrib, keyAlias, childElem); bool isValueFound = VerifyDictionaryPairElements(ref valueType, ref isValueAttrib, valueAlias, childElem); if (!isKeyFound && !isValueFound) continue; if (isKeyFound) { if (isKeyAttrib) { key = ReflectionUtils.ConvertBasicType(childElem.Attribute(keyAlias).Value, keyType); } else if (ReflectionUtils.IsBasicType(keyType)) { key = ReflectionUtils.ConvertBasicType(childElem.Element(keyAlias).Value, keyType); } else { if (keySer == null) { keySer = new YAXSerializer(keyType, this.m_exceptionPolicy, this.m_defaultExceptionType, this.m_serializationOption); } key = keySer.DeserializeBase(childElem.Element(keyAlias)); this.m_parsingErrors.AddRange(keySer.ParsingErrors); } } if (isValueFound) { if (isValueAttrib) { value = ReflectionUtils.ConvertBasicType(childElem.Attribute(valueAlias).Value, valueType); } else if (ReflectionUtils.IsBasicType(valueType)) { value = ReflectionUtils.ConvertBasicType(childElem.Element(valueAlias).Value, valueType); } else { if (valueSer == null) { valueSer = new YAXSerializer(valueType, this.m_exceptionPolicy, this.m_defaultExceptionType, this.m_serializationOption); } value = valueSer.DeserializeBase(childElem.Element(valueAlias)); m_parsingErrors.AddRange(valueSer.ParsingErrors); } } try { memberType.InvokeMember("Add", BindingFlags.InvokeMethod, null, dic, new object[] { key, value }); } catch { this.OnExceptionOccurred( new YAXCannotAddObjectToCollection(member.Alias, new KeyValuePair<object, object>(key, value)), this.m_defaultExceptionType); } } try { member.SetValue(o, dic); } catch { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias), this.m_defaultExceptionType); } }
/// <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; } } } }
public bool HasShouldSerialiseMethod(MemberWrapper member) { return(FindShouldSerializeMethod(member) != null); }
/// <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; // when serializing collection with no containing element, then the real type attribute applies to the class // containing the collection, not the collection itself. That's because the containing element of collection is not // serialized. In this case the flag `isRealTypeAttributeNotRelevant` is set to true. bool isRealTypeAttributeNotRelevant = member.CollectionAttributeInstance != null && member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement; // try to retrieve the real-type if specified if (xelemValue != null && !isRealTypeAttributeNotRelevant) { 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 namespaceToOverride = member.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone(); var ser = NewInternalSerializer(memberType, namespaceToOverride, null); 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); FinalizeNewSerializer(ser, false); try { member.SetValue(o, convertedObj); } catch { OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } }
/// <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 == '_') && // TODO: this is wrong, .NET supports unicode variable names or those starting with @ (member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field)) { var prop = member as PropertyInfo; if (prop != null) { // ignore indexers; if member is an indexer property, do not serialize it if (prop.GetIndexParameters().Length > 0) continue; // don't serialize delegates as well if (ReflectionUtils.IsTypeEqualOrInheritedFromType(prop.PropertyType, typeof(Delegate))) continue; } if((typeWrapper.IsCollectionType || typeWrapper.IsDictionaryType)) //&& typeWrapper.IsAttributedAsNotCollection) if(ReflectionUtils.IsPartOfNetFx(member)) continue; var memInfo = new MemberWrapper(member, this); if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize, m_udtWrapper.DontSerializePropertiesWithNoSetter)) { yield return memInfo; } } } }