/// <summary> /// Creates a dictionary element according to the specified options, as described /// by the attribute instances. /// </summary> /// <param name="insertionLocation">The insertion location.</param> /// <param name="elementName">Name of the element.</param> /// <param name="elementValue">The element value, corresponding to a dictionary object.</param> /// <param name="dicAttrInst">reference to the dictionary attribute instance.</param> /// <param name="collectionAttrInst">reference to collection attribute instance.</param> /// <returns> /// an instance of <c>XElement</c> which contains the dictionary object /// serialized properly /// </returns> private XElement MakeDictionaryElement( XElement insertionLocation, XName elementName, object elementValue, YAXDictionaryAttribute dicAttrInst, YAXCollectionAttribute collectionAttrInst) { if (elementValue == null) { return new XElement(elementName, elementValue); } Type keyType, valueType; if (!ReflectionUtils.IsIDictionary(elementValue.GetType(), out keyType, out valueType)) { throw new ArgumentException("elementValue must be a Dictionary"); } var dicInst = elementValue as IEnumerable; bool isKeyAttrib = false; bool isValueAttrib = false; bool isKeyContent = false; bool isValueContent = false; string keyFormat = null; string valueFormat = null; XName keyAlias = elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Key"; XName valueAlias = elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Value"; XName eachElementName = null; if (collectionAttrInst != null && !String.IsNullOrEmpty(collectionAttrInst.EachElementName)) { eachElementName = StringUtils.RefineSingleElement(collectionAttrInst.EachElementName); if (eachElementName.Namespace.HasNamespace()) RegisterNamespace(eachElementName.Namespace, null); eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInst != null) { if (dicAttrInst.EachPairName != null) { eachElementName = StringUtils.RefineSingleElement(dicAttrInst.EachPairName); if (eachElementName.Namespace.HasNamespace()) RegisterNamespace(eachElementName.Namespace, null); eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInst.SerializeKeyAs == YAXNodeTypes.Attribute) { isKeyAttrib = ReflectionUtils.IsBasicType(keyType); } else if (dicAttrInst.SerializeKeyAs == YAXNodeTypes.Content) { isKeyContent = ReflectionUtils.IsBasicType(keyType); } if (dicAttrInst.SerializeValueAs == YAXNodeTypes.Attribute) { isValueAttrib = ReflectionUtils.IsBasicType(valueType); } else if (dicAttrInst.SerializeValueAs == YAXNodeTypes.Content) { isValueContent = ReflectionUtils.IsBasicType(valueType); } keyFormat = dicAttrInst.KeyFormatString; valueFormat = dicAttrInst.ValueFormatString; keyAlias = StringUtils.RefineSingleElement(dicAttrInst.KeyName ?? "Key"); if (keyAlias.Namespace.HasNamespace()) RegisterNamespace(keyAlias.Namespace, null); keyAlias = keyAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); valueAlias = StringUtils.RefineSingleElement(dicAttrInst.ValueName ?? "Value"); if (valueAlias.Namespace.HasNamespace()) RegisterNamespace(valueAlias.Namespace, null); valueAlias = valueAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } XElement elem = new XElement(elementName, null); foreach (object obj in dicInst) { object keyObj = obj.GetType().GetProperty("Key").GetValue(obj, null); object valueObj = obj.GetType().GetProperty("Value").GetValue(obj, null); bool areKeyOfSameType = true; bool areValueOfSameType = true; if (keyObj != null && !keyObj.GetType().EqualsOrIsNullableOf(keyType)) areKeyOfSameType = false; if (valueObj != null && !valueObj.GetType().EqualsOrIsNullableOf(valueType)) areValueOfSameType = false; if (keyFormat != null) { keyObj = ReflectionUtils.TryFormatObject(keyObj, keyFormat); } if (valueFormat != null) { valueObj = ReflectionUtils.TryFormatObject(valueObj, valueFormat); } if (eachElementName == null) { eachElementName = StringUtils.RefineSingleElement(ReflectionUtils.GetTypeFriendlyName(obj.GetType())); eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } XElement elemChild = new XElement(eachElementName, null); if (isKeyAttrib && areKeyOfSameType) { elemChild.AddAttributeNamespaceSafe(keyAlias, keyObj); } else if (isKeyContent && areKeyOfSameType) { elemChild.AddXmlContent(keyObj); } else { XElement addedElem = AddObjectToElement(elemChild, keyAlias, keyObj); if (!areKeyOfSameType) { if (addedElem.Parent == null) { // sometimes empty elements are removed because its members are serialized in // other elements, therefore we need to make sure to re-add the element. elemChild.Add(addedElem); } addedElem.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, keyObj.GetType().FullName); RegisterYaxLibNamespace(); } } if (isValueAttrib && areValueOfSameType) { elemChild.AddAttributeNamespaceSafe(valueAlias, valueObj); } else if (isValueContent && areValueOfSameType) { elemChild.AddXmlContent(valueObj); } else { XElement addedElem = AddObjectToElement(elemChild, valueAlias, valueObj); if (!areValueOfSameType) { if (addedElem.Parent == null) { // sometimes empty elements are removed because its members are serialized in // other elements, therefore we need to make sure to re-add the element. elemChild.Add(addedElem); } addedElem.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, valueObj.GetType().FullName); RegisterYaxLibNamespace(); } } elem.Add(elemChild); } return elem; }
/// <summary> /// Initializes a new instance of the <see cref="MemberWrapper" /> class. /// </summary> /// <param name="memberInfo">The member-info to build this instance from.</param> /// <param name="callerSerializer">The caller serializer.</param> public MemberWrapper(MemberInfo memberInfo, YAXSerializer callerSerializer) { Order = int.MaxValue; if (!(memberInfo.MemberType == MemberTypes.Property || memberInfo.MemberType == MemberTypes.Field)) { throw new Exception("Member must be either property or field"); } _memberInfo = memberInfo; _isProperty = memberInfo.MemberType == MemberTypes.Property; Alias = StringUtils.RefineSingleElement(_memberInfo.Name); if (_isProperty) { _propertyInfoInstance = (PropertyInfo)memberInfo; } else { _fieldInfoInstance = (FieldInfo)memberInfo; } _memberType = _isProperty ? _propertyInfoInstance.PropertyType : _fieldInfoInstance.FieldType; _memberTypeWrapper = TypeWrappersPool.Pool.GetTypeWrapper(MemberType, callerSerializer); if (_memberTypeWrapper.HasNamespace) { Namespace = _memberTypeWrapper.Namespace; NamespacePrefix = _memberTypeWrapper.NamespacePrefix; } InitInstance(); TreatErrorsAs = callerSerializer != null ? callerSerializer.DefaultExceptionType : YAXExceptionTypes.Error; // discover YAXCustomSerializerAttributes earlier, because some other attributes depend on it var attrsToProcessEarlier = new HashSet <Type> { typeof(YAXCustomSerializerAttribute), typeof(YAXCollectionAttribute) }; foreach (var attrType in attrsToProcessEarlier) { var customSerAttrs = Attribute.GetCustomAttributes(_memberInfo, attrType, true); foreach (var attr in customSerAttrs) { ProcessYaxAttribute(attr); } } foreach (var attr in Attribute.GetCustomAttributes(_memberInfo, true)) { // no need to process, it has been processed earlier if (attrsToProcessEarlier.Contains(attr.GetType())) { continue; } if (attr is YAXBaseAttribute) { ProcessYaxAttribute(attr); } } // now override some values from member-type-wrapper into member-wrapper // if member-type has collection attributes while the member itself does not have them, // then use those of the member-type if (_collectionAttributeInstance == null && _memberTypeWrapper.CollectionAttributeInstance != null) { _collectionAttributeInstance = _memberTypeWrapper.CollectionAttributeInstance; } _memberInfo.GetCustomAttributes(true); if (_dictionaryAttributeInstance == null && _memberTypeWrapper.DictionaryAttributeInstance != null) { _dictionaryAttributeInstance = _memberTypeWrapper.DictionaryAttributeInstance; } }
private object DeserializeTaggedDictionaryValue(XElement xelemValue, XName alias, Type type, YAXCollectionAttribute colAttributeInstance, YAXDictionaryAttribute dicAttrInstance) { // otherwise the "else if(member.IsTreatedAsCollection)" block solves the problem Type keyType, valueType; if (!ReflectionUtils.IsIDictionary(type, out keyType, out valueType)) { throw new Exception("elemValue must be a Dictionary"); } Type pairType = null; ReflectionUtils.IsIEnumerable(type, out pairType); XName eachElementName = StringUtils.RefineSingleElement(ReflectionUtils.GetTypeFriendlyName(pairType)); bool isKeyAttrib = false; bool isValueAttrib = false; bool isKeyContent = false; bool isValueContent = false; XName keyAlias = alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Key"; XName valueAlias = alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Value"; if (colAttributeInstance != null && colAttributeInstance.EachElementName != null) { eachElementName = StringUtils.RefineSingleElement(colAttributeInstance.EachElementName); eachElementName = eachElementName.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance != null) { if (dicAttrInstance.EachPairName != null) { eachElementName = StringUtils.RefineSingleElement(dicAttrInstance.EachPairName); eachElementName = eachElementName.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance.SerializeKeyAs == YAXNodeTypes.Attribute) { isKeyAttrib = ReflectionUtils.IsBasicType(keyType); } else if (dicAttrInstance.SerializeKeyAs == YAXNodeTypes.Content) { isKeyContent = ReflectionUtils.IsBasicType(keyType); } if (dicAttrInstance.SerializeValueAs == YAXNodeTypes.Attribute) { isValueAttrib = ReflectionUtils.IsBasicType(valueType); } else if (dicAttrInstance.SerializeValueAs == YAXNodeTypes.Content) { isValueContent = ReflectionUtils.IsBasicType(valueType); } if (dicAttrInstance.KeyName != null) { keyAlias = StringUtils.RefineSingleElement(dicAttrInstance.KeyName); keyAlias = keyAlias.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance.ValueName != null) { valueAlias = StringUtils.RefineSingleElement(dicAttrInstance.ValueName); valueAlias = valueAlias.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } } object dic = type.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, ref isKeyContent, keyAlias, childElem); bool isValueFound = VerifyDictionaryPairElements(ref valueType, ref isValueAttrib, ref isValueContent, valueAlias, childElem); if (!isKeyFound && !isValueFound) continue; if (isKeyFound) { if (isKeyAttrib) { key = ReflectionUtils.ConvertBasicType(childElem.Attribute_NamespaceSafe(keyAlias).Value, keyType); } else if (isKeyContent) { key = ReflectionUtils.ConvertBasicType(childElem.GetXmlContent(), keyType); } else if (ReflectionUtils.IsBasicType(keyType)) { key = ReflectionUtils.ConvertBasicType(childElem.Element(keyAlias).Value, keyType); } else { if (keySer == null) { keySer = new YAXSerializer(keyType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption); keySer.SetNamespaceToOverrideEmptyNamespace(keyAlias.Namespace); } key = keySer.DeserializeBase(childElem.Element(keyAlias)); m_parsingErrors.AddRange(keySer.ParsingErrors); } } if (isValueFound) { if (isValueAttrib) { value = ReflectionUtils.ConvertBasicType(childElem.Attribute_NamespaceSafe(valueAlias).Value, valueType); } else if (isValueContent) { value = ReflectionUtils.ConvertBasicType(childElem.GetXmlContent(), valueType); } else if (ReflectionUtils.IsBasicType(valueType)) { value = ReflectionUtils.ConvertBasicType(childElem.Element(valueAlias).Value, valueType); } else { if (valueSer == null) { valueSer = new YAXSerializer(valueType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption); valueSer.SetNamespaceToOverrideEmptyNamespace(valueAlias.Namespace); } value = valueSer.DeserializeBase(childElem.Element(valueAlias)); m_parsingErrors.AddRange(valueSer.ParsingErrors); } } try { type.InvokeMember("Add", BindingFlags.InvokeMethod, null, dic, new object[] { key, value }); } catch { this.OnExceptionOccurred( new YAXCannotAddObjectToCollection(alias.LocalName, new KeyValuePair<object, object>(key, value)), m_defaultExceptionType); } } return dic; }
/// <summary> /// Processes the specified attribute which is an instance of <c>YAXAttribute</c>. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYaxAttribute(object attr) { if (attr is YAXCommentAttribute) { string comment = (attr as YAXCommentAttribute).Comment; if (!String.IsNullOrEmpty(comment)) { string[] comments = comment.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < comments.Length; i++) { comments[i] = String.Format(" {0} ", comments[i].Trim()); } this.Comment = comments; } } else if (attr is YAXSerializableFieldAttribute) { IsAttributedAsSerializable = true; } else if (attr is YAXAttributeForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; SerializationLocation = "."; } } else if (attr is YAXValueForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; SerializationLocation = "."; } } else if (attr is YAXAttributeForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXAttributeForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = StringUtils.RefineSingleElement(alias); } } else if (attr is YAXElementForAttribute) { IsSerializedAsElement = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXElementForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = StringUtils.RefineSingleElement(alias); } else if (attr is YAXValueForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(this.MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXValueForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = StringUtils.RefineSingleElement(alias); } } else if (attr is YAXDontSerializeAttribute) { IsAttributedAsDontSerialize = true; } else if (attr is YAXSerializeAsAttribute) { Alias = StringUtils.RefineSingleElement((attr as YAXSerializeAsAttribute).SerializeAs); } else if (attr is YAXCollectionAttribute) { m_collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { m_dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else if (attr is YAXErrorIfMissedAttribute) { var temp = attr as YAXErrorIfMissedAttribute; DefaultValue = temp.DefaultValue; TreatErrorsAs = temp.TreatAs; } else if (attr is YAXFormatAttribute) { Format = (attr as YAXFormatAttribute).Format; } else if (attr is YAXNotCollectionAttribute) { // arrays are always treated as collections if (!ReflectionUtils.IsArray(MemberType)) IsAttributedAsNotCollection = true; } else if (attr is YAXCustomSerializerAttribute) { Type serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer<>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException("The provided custom serialization type is not derived from the proper interface"); } else if (genTypeArg != this.MemberType) { throw new YAXException("The generic argument of the class and the member type do not match"); } else { CustomSerializerType = serType; } } else if(attr is YAXPreserveWhitespaceAttribute) { PreservesWhitespace = true; } else if (attr is YAXSerializableTypeAttribute) { // this should not happen throw new Exception("This attribute is not applicable to fields and properties!"); } else if (attr is YAXNamespaceAttribute) { var nsAttrib = (attr as YAXNamespaceAttribute); Namespace = nsAttrib.Namespace; NamespacePrefix = nsAttrib.Prefix; } else if (attr is YAXTypeAttribute) { var yaxTypeAttr = attr as YAXTypeAttribute; string alias = yaxTypeAttr.Alias; if (alias != null) { alias = alias.Trim(); if (alias.Length == 0) alias = null; } if(m_possibleRealTypes.Any(x => x.Type == yaxTypeAttr.Type)) throw new YAXPolymorphicException(String.Format("The type \"{0}\" for field/property \"{1}\" has already been defined through another attribute.", yaxTypeAttr.Type.Name, m_memberInfo)); if (alias != null && m_possibleRealTypes.Any(x => alias.Equals(x.Alias, StringComparison.Ordinal))) throw new YAXPolymorphicException(String.Format("The alias \"{0}\" given to type \"{1}\" for field/property \"{2}\" has already been given to another type through another attribute.", alias, yaxTypeAttr.Type.Name, m_memberInfo)); m_possibleRealTypes.Add(yaxTypeAttr); } else if (attr is YAXCollectionItemTypeAttribute) { var yaxColletionItemTypeAttr = attr as YAXCollectionItemTypeAttribute; string alias = yaxColletionItemTypeAttr.Alias; if (alias != null) { alias = alias.Trim(); if (alias.Length == 0) alias = null; } if (m_possibleCollectionItemRealTypes.Any(x => x.Type == yaxColletionItemTypeAttr.Type)) throw new YAXPolymorphicException(String.Format("The collection-item type \"{0}\" for collection \"{1}\" has already been defined through another attribute.", yaxColletionItemTypeAttr.Type.Name, m_memberInfo)); if (alias != null && m_possibleCollectionItemRealTypes.Any(x => alias.Equals(x.Alias, StringComparison.Ordinal))) throw new YAXPolymorphicException(String.Format("The alias \"{0}\" given to collection-item type \"{1}\" for field/property \"{2}\" has already been given to another type through another attribute.", alias, yaxColletionItemTypeAttr.Type.Name, m_memberInfo)); m_possibleCollectionItemRealTypes.Add(yaxColletionItemTypeAttr); } else if (attr is YAXDontSerializeIfNullAttribute) { IsAttributedAsDontSerializeIfNull = true; } else if (attr is YAXElementOrder) { Order = (attr as YAXElementOrder).Order; } else { throw new Exception("Added new attribute type to the library but not yet processed!"); } }
/// <summary> /// Processes the specified attribute which is an instance of <c>YAXAttribute</c>. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYaxAttribute(object attr) { if (attr is YAXCommentAttribute) { var comment = (attr as YAXCommentAttribute).Comment; if (!string.IsNullOrEmpty(comment)) { var comments = comment.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (var i = 0; i < comments.Length; i++) { comments[i] = string.Format(" {0} ", comments[i].Trim()); } Comment = comments; } } else if (attr is YAXSerializableFieldAttribute) { IsAttributedAsSerializable = true; } else if (attr is YAXAttributeForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || HasCustomSerializer || MemberTypeWrapper.HasCustomSerializer || _collectionAttributeInstance != null && _collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially) { IsSerializedAsAttribute = true; SerializationLocation = "."; } } else if (attr is YAXValueForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || HasCustomSerializer || MemberTypeWrapper.HasCustomSerializer || _collectionAttributeInstance != null && _collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially) { IsSerializedAsValue = true; SerializationLocation = "."; } } else if (attr is YAXAttributeForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || HasCustomSerializer || _collectionAttributeInstance != null && _collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially) { IsSerializedAsAttribute = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXAttributeForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!string.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } } else if (attr is YAXElementForAttribute) { IsSerializedAsElement = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXElementForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!string.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } else if (attr is YAXValueForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || HasCustomSerializer || _collectionAttributeInstance != null && _collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially) { IsSerializedAsValue = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXValueForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!string.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } } else if (attr is YAXDontSerializeAttribute) { IsAttributedAsDontSerialize = true; } else if (attr is YAXSerializeAsAttribute) { Alias = StringUtils.RefineSingleElement((attr as YAXSerializeAsAttribute).SerializeAs); } else if (attr is YAXCollectionAttribute) { _collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { _dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else if (attr is YAXErrorIfMissedAttribute) { var temp = attr as YAXErrorIfMissedAttribute; DefaultValue = temp.DefaultValue; TreatErrorsAs = temp.TreatAs; } else if (attr is YAXFormatAttribute) { Format = (attr as YAXFormatAttribute).Format; } else if (attr is YAXNotCollectionAttribute) { // arrays are always treated as collections if (!ReflectionUtils.IsArray(MemberType)) { IsAttributedAsNotCollection = true; } } else if (attr is YAXCustomSerializerAttribute) { var serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; var isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer <>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException( "The provided custom serialization type is not derived from the proper interface"); } if (genTypeArg != MemberType) { throw new YAXException("The generic argument of the class and the member type do not match"); } CustomSerializerType = serType; } else if (attr is YAXPreserveWhitespaceAttribute) { PreservesWhitespace = true; } else if (attr is YAXSerializableTypeAttribute) { // this should not happen throw new Exception("This attribute is not applicable to fields and properties!"); } else if (attr is YAXNamespaceAttribute) { var nsAttrib = attr as YAXNamespaceAttribute; Namespace = nsAttrib.Namespace; NamespacePrefix = nsAttrib.Prefix; } else if (attr is YAXTypeAttribute) { var yaxTypeAttr = attr as YAXTypeAttribute; var alias = yaxTypeAttr.Alias; if (alias != null) { alias = alias.Trim(); if (alias.Length == 0) { alias = null; } } if (_possibleRealTypes.Any(x => x.Type == yaxTypeAttr.Type)) { throw new YAXPolymorphicException(string.Format( "The type \"{0}\" for field/property \"{1}\" has already been defined through another attribute.", yaxTypeAttr.Type.Name, _memberInfo)); } if (alias != null && _possibleRealTypes.Any(x => alias.Equals(x.Alias, StringComparison.Ordinal))) { throw new YAXPolymorphicException(string.Format( "The alias \"{0}\" given to type \"{1}\" for field/property \"{2}\" has already been given to another type through another attribute.", alias, yaxTypeAttr.Type.Name, _memberInfo)); } _possibleRealTypes.Add(yaxTypeAttr); } else if (attr is YAXCollectionItemTypeAttribute) { var yaxColletionItemTypeAttr = attr as YAXCollectionItemTypeAttribute; var alias = yaxColletionItemTypeAttr.Alias; if (alias != null) { alias = alias.Trim(); if (alias.Length == 0) { alias = null; } } if (_possibleCollectionItemRealTypes.Any(x => x.Type == yaxColletionItemTypeAttr.Type)) { throw new YAXPolymorphicException(string.Format( "The collection-item type \"{0}\" for collection \"{1}\" has already been defined through another attribute.", yaxColletionItemTypeAttr.Type.Name, _memberInfo)); } if (alias != null && _possibleCollectionItemRealTypes.Any(x => alias.Equals(x.Alias, StringComparison.Ordinal))) { throw new YAXPolymorphicException(string.Format( "The alias \"{0}\" given to collection-item type \"{1}\" for field/property \"{2}\" has already been given to another type through another attribute.", alias, yaxColletionItemTypeAttr.Type.Name, _memberInfo)); } _possibleCollectionItemRealTypes.Add(yaxColletionItemTypeAttr); } else if (attr is YAXDontSerializeIfNullAttribute) { IsAttributedAsDontSerializeIfNull = true; } else if (attr is YAXElementOrder) { Order = (attr as YAXElementOrder).Order; } else { throw new Exception("Added new attribute type to the library but not yet processed!"); } }
/// <summary> /// Processes the specified attribute. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYAXAttribute(object attr) { if (attr is YAXCommentAttribute) { string comment = (attr as YAXCommentAttribute).Comment; if(!String.IsNullOrEmpty(comment)) { string[] comments = comment.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for(int i = 0; i < comments.Length; i++) { comments[i] = String.Format(" {0} ", comments[i].Trim()); } this.Comment = comments; } } else if (attr is YAXSerializableTypeAttribute) { var theAttr = attr as YAXSerializableTypeAttribute; this.FieldsToSerialize = theAttr.FieldsToSerialize; if (theAttr.IsSerializationOptionSet()) { SerializationOption = theAttr.Options; m_isSerializationOptionSetByAttribute = true; } } else if (attr is YAXSerializeAsAttribute) { Alias = StringUtils.RefineSingleElement((attr as YAXSerializeAsAttribute).SerializeAs); } else if (attr is YAXNotCollectionAttribute) { if(!ReflectionUtils.IsArray(m_udtType)) IsAttributedAsNotCollection = true; } else if (attr is YAXCustomSerializerAttribute) { Type serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer<>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException("The provided custom serialization type is not derived from the proper interface"); } if (genTypeArg != UnderlyingType) { throw new YAXException("The generic argument of the class and the type of the class do not match"); } this.CustomSerializerType = serType; } else if(attr is YAXPreserveWhitespaceAttribute) { PreservesWhitespace = true; } else if (attr is YAXNamespaceAttribute) { var nsAttrib = (attr as YAXNamespaceAttribute); Namespace = nsAttrib.Namespace; NamespacePrefix = nsAttrib.Prefix; } else if (attr is YAXCollectionAttribute) { m_collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { m_dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else { throw new Exception("Attribute not applicable to types!"); } }
/// <summary> /// Initializes a new instance of the <see cref="MemberWrapper"/> class. /// </summary> /// <param name="memberInfo">The member-info to build this instance from.</param> /// <param name="callerSerializer">The caller serializer.</param> public MemberWrapper(MemberInfo memberInfo, YAXSerializer callerSerializer) { Order = Int32.MaxValue; if (!(memberInfo.MemberType == MemberTypes.Property || memberInfo.MemberType == MemberTypes.Field)) throw new Exception("Member must be either property or field"); m_memberInfo = memberInfo; m_isProperty = (memberInfo.MemberType == MemberTypes.Property); Alias = StringUtils.RefineSingleElement(m_memberInfo.Name); if (m_isProperty) m_propertyInfoInstance = (PropertyInfo)memberInfo; else m_fieldInfoInstance = (FieldInfo)memberInfo; m_memberType = m_isProperty ? m_propertyInfoInstance.PropertyType : m_fieldInfoInstance.FieldType; m_memberTypeWrapper = TypeWrappersPool.Pool.GetTypeWrapper(MemberType, callerSerializer); if (m_memberTypeWrapper.HasNamespace) { Namespace = m_memberTypeWrapper.Namespace; NamespacePrefix = m_memberTypeWrapper.NamespacePrefix; } InitInstance(); TreatErrorsAs = callerSerializer != null ? callerSerializer.DefaultExceptionType : YAXExceptionTypes.Error; // discovver YAXCustomSerializerAttributes earlier, because some other attributes depend on it var attrsToProcessEarlier = new HashSet<Type> {typeof (YAXCustomSerializerAttribute), typeof (YAXCollectionAttribute)}; foreach (var attrType in attrsToProcessEarlier) { var customSerAttrs = Attribute.GetCustomAttributes(m_memberInfo, attrType, true); foreach (var attr in customSerAttrs) { ProcessYaxAttribute(attr); } } foreach (var attr in Attribute.GetCustomAttributes(m_memberInfo, true)) { // no need to preces, it has been proccessed earlier if (attrsToProcessEarlier.Contains(attr.GetType())) continue; if (attr is YAXBaseAttribute) ProcessYaxAttribute(attr); } // now override some values from memeber-type-wrapper into member-wrapper // if member-type has collection attributes while the member itself does not have them, // then use those of the member-type if (m_collectionAttributeInstance == null && m_memberTypeWrapper.CollectionAttributeInstance != null) m_collectionAttributeInstance = m_memberTypeWrapper.CollectionAttributeInstance; if (m_dictionaryAttributeInstance == null && m_memberTypeWrapper.DictionaryAttributeInstance != null) m_dictionaryAttributeInstance = m_memberTypeWrapper.DictionaryAttributeInstance; }
/// <summary> /// Processes the specified attribute which is an instance of <c>YAXAttribute</c>. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYaxAttribute(object attr) { if (attr is YAXCommentAttribute) { string comment = (attr as YAXCommentAttribute).Comment; if (!String.IsNullOrEmpty(comment)) { string[] comments = comment.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < comments.Length; i++) { comments[i] = String.Format(" {0} ", comments[i].Trim()); } this.Comment = comments; } } else if (attr is YAXSerializableFieldAttribute) { IsAttributedAsSerializable = true; } else if (attr is YAXAttributeForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; SerializationLocation = "."; } } else if (attr is YAXValueForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; SerializationLocation = "."; } } else if (attr is YAXAttributeForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXAttributeForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = alias; } } else if (attr is YAXElementForAttribute) { IsSerializedAsElement = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXElementForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = alias; } else if (attr is YAXValueForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(this.MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXValueForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) Alias = alias; } } else if (attr is YAXDontSerializeAttribute) { IsAttributedAsDontSerialize = true; } else if (attr is YAXSerializeAsAttribute) { Alias = (attr as YAXSerializeAsAttribute).SerializeAs; } else if (attr is YAXCollectionAttribute) { m_collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { m_dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else if (attr is YAXErrorIfMissedAttribute) { var temp = attr as YAXErrorIfMissedAttribute; DefaultValue = temp.DefaultValue; TreatErrorsAs = temp.TreatAs; } else if (attr is YAXFormatAttribute) { Format = (attr as YAXFormatAttribute).Format; } else if (attr is YAXNotCollectionAttribute) { // arrays are always treated as collections if (!ReflectionUtils.IsArray(MemberType)) IsAttributedAsNotCollection = true; } else if (attr is YAXCustomSerializerAttribute) { Type serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer<>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException("The provided custom serialization type is not derived from the proper interface"); } else if (genTypeArg != this.MemberType) { throw new YAXException("The generic argument of the class and the member type do not match"); } else { CustomSerializerType = serType; } } //else if (attr is YAXCustomDeserializerAttribute) //{ // Type deserType = (attr as YAXCustomDeserializerAttribute).CustomDeserializerType; // Type genTypeArg; // bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(deserType, typeof(ICustomSerializer<>), out genTypeArg); // if (!isDesiredInterface) // { // throw new YAXException("The provided custom deserialization type is not derived from the proper interface"); // } // else if (genTypeArg != this.MemberType) // { // throw new YAXException("The generic argument of the class and the member type do not match"); // } // else // { // this.CustomDeserializerType = deserType; // } //} else if (attr is YAXSerializableTypeAttribute) { // this should not happen throw new Exception("This attribute is not applicable to fields and properties!"); } else { throw new Exception("Added new attribute type to the library but not yet processed!"); } }
/// <summary> /// Creates a dictionary element according to the specified options, as described /// by the attribute instances. /// </summary> /// <param name="insertionLocation">The insertion location.</param> /// <param name="elementName">Name of the element.</param> /// <param name="elementValue">The element value, corresponding to a dictionary object.</param> /// <param name="dicAttrInst">reference to the dictionary attribute instance.</param> /// <param name="collectionAttrInst">reference to collection attribute instance.</param> /// <returns> /// an instance of <c>XElement</c> which contains the dictionary object /// serialized properly /// </returns> private XElement MakeDictionaryElement( XElement insertionLocation, string elementName, object elementValue, YAXDictionaryAttribute dicAttrInst, YAXCollectionAttribute collectionAttrInst) { if (elementValue == null) { return new XElement(elementName, elementValue); } Type keyType, valueType; if (!ReflectionUtils.IsIDictionary(elementValue.GetType(), out keyType, out valueType)) { throw new ArgumentException("elementValue must be a Dictionary"); } var dicInst = elementValue as IEnumerable; bool isKeyAttrib = false; bool isValueAttrib = false; string keyFormat = null; string valueFormat = null; string keyAlias = "Key"; string valueAlias = "Value"; string eachElementName = collectionAttrInst != null ? collectionAttrInst.EachElementName : null; if (dicAttrInst != null) { eachElementName = dicAttrInst.EachPairName ?? eachElementName; if (dicAttrInst.SerializeKeyAs == YAXNodeTypes.Attribute) { isKeyAttrib = ReflectionUtils.IsBasicType(keyType); } if (dicAttrInst.SerializeValueAs == YAXNodeTypes.Attribute) { isValueAttrib = ReflectionUtils.IsBasicType(valueType); } keyFormat = dicAttrInst.KeyFormatString; valueFormat = dicAttrInst.ValueFormatString; keyAlias = dicAttrInst.KeyName ?? "Key"; valueAlias = dicAttrInst.ValueName ?? "Value"; } XElement elem = new XElement(elementName, null); foreach (object obj in dicInst) { object keyObj = obj.GetType().GetProperty("Key").GetValue(obj, null); object valueObj = obj.GetType().GetProperty("Value").GetValue(obj, null); bool areKeyOfSameType = true; bool areValueOfSameType = true; if (keyObj != null && keyObj.GetType() != keyType) areKeyOfSameType = false; if (valueObj != null && valueObj.GetType() != valueType) areValueOfSameType = false; if (keyFormat != null) { keyObj = ReflectionUtils.TryFormatObject(keyObj, keyFormat); } if (valueFormat != null) { valueObj = ReflectionUtils.TryFormatObject(valueObj, valueFormat); } XElement elemChild = new XElement(eachElementName ?? ReflectionUtils.GetTypeFriendlyName(obj.GetType()), null); if (isKeyAttrib && areKeyOfSameType) { elemChild.Add(new XAttribute(keyAlias, (keyObj ?? string.Empty).ToString())); } else { XElement addedElem = AddObjectToElement(elemChild, keyAlias, keyObj); if (!areKeyOfSameType) { if (addedElem.Parent == null) { // sometimes empty elements are removed because its members are serialized in // other elements, therefore we need to make sure to re-add the element. elemChild.Add(addedElem); } addedElem.Add(new XAttribute(s_namespaceURI + s_trueTypeAttrName, keyObj.GetType().FullName)); m_needsNamespaceAddition = true; } } if (isValueAttrib && areValueOfSameType) { elemChild.Add(new XAttribute(valueAlias, (valueObj ?? string.Empty).ToString())); } else { XElement addedElem = AddObjectToElement(elemChild, valueAlias, valueObj); if (!areValueOfSameType) { if(addedElem.Parent == null) { // sometimes empty elements are removed because its members are serialized in // other elements, therefore we need to make sure to re-add the element. elemChild.Add(addedElem); } addedElem.Add(new XAttribute(s_namespaceURI + s_trueTypeAttrName, valueObj.GetType().FullName)); m_needsNamespaceAddition = true; } } elem.Add(elemChild); } return elem; }
/// <summary> /// Processes the specified attribute. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYAXAttribute(object attr) { if (attr is YAXCommentAttribute) { string comment = (attr as YAXCommentAttribute).Comment; if (!String.IsNullOrEmpty(comment)) { string[] comments = comment.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < comments.Length; i++) { comments[i] = String.Format(" {0} ", comments[i].Trim()); } this.Comment = comments; } } else if (attr is YAXSerializableTypeAttribute) { var theAttr = attr as YAXSerializableTypeAttribute; this.FieldsToSerialize = theAttr.FieldsToSerialize; if (theAttr.IsSerializationOptionSet()) { this.SerializationOption = theAttr.Options; this.m_isSerializationOptionSetByAttribute = true; } } else if (attr is YAXSerializeAsAttribute) { this.Alias = StringUtils.RefineSingleElement((attr as YAXSerializeAsAttribute).SerializeAs); } else if (attr is YAXNotCollectionAttribute) { if (!ReflectionUtils.IsArray(this.m_udtType)) { this.IsAttributedAsNotCollection = true; } } else if (attr is YAXCustomSerializerAttribute) { Type serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer <>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException("The provided custom serialization type is not derived from the proper interface"); } if (genTypeArg != this.UnderlyingType) { throw new YAXException("The generic argument of the class and the type of the class do not match"); } this.CustomSerializerType = serType; } else if (attr is YAXPreserveWhitespaceAttribute) { this.PreservesWhitespace = true; } else if (attr is YAXNamespaceAttribute) { var nsAttrib = (attr as YAXNamespaceAttribute); this.Namespace = nsAttrib.Namespace; this.NamespacePrefix = nsAttrib.Prefix; } else if (attr is YAXCollectionAttribute) { this.m_collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { this.m_dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else { throw new Exception("Attribute not applicable to types!"); } }
/// <summary> /// Processes the specified attribute which is an instance of <c>YAXAttribute</c>. /// </summary> /// <param name="attr">The attribute to process.</param> private void ProcessYaxAttribute(object attr) { if (attr is YAXCommentAttribute) { string comment = (attr as YAXCommentAttribute).Comment; if (!String.IsNullOrEmpty(comment)) { string[] comments = comment.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < comments.Length; i++) { comments[i] = String.Format(" {0} ", comments[i].Trim()); } this.Comment = comments; } } else if (attr is YAXSerializableFieldAttribute) { IsAttributedAsSerializable = true; } else if (attr is YAXAttributeForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; SerializationLocation = "."; } } else if (attr is YAXValueForClassAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; SerializationLocation = "."; } } else if (attr is YAXAttributeForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsAttribute = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXAttributeForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } } else if (attr is YAXElementForAttribute) { IsSerializedAsElement = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXElementForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } else if (attr is YAXValueForAttribute) { // it is required that YAXCustomSerializerAttribute is processed earlier if (ReflectionUtils.IsBasicType(this.MemberType) || CustomSerializerType != null || (m_collectionAttributeInstance != null && m_collectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.Serially)) { IsSerializedAsValue = true; string path, alias; StringUtils.ExttractPathAndAliasFromLocationString((attr as YAXValueForAttribute).Parent, out path, out alias); SerializationLocation = path; if (!String.IsNullOrEmpty(alias)) { Alias = StringUtils.RefineSingleElement(alias); } } } else if (attr is YAXDontSerializeAttribute) { IsAttributedAsDontSerialize = true; } else if (attr is YAXSerializeAsAttribute) { Alias = StringUtils.RefineSingleElement((attr as YAXSerializeAsAttribute).SerializeAs); } else if (attr is YAXCollectionAttribute) { m_collectionAttributeInstance = attr as YAXCollectionAttribute; } else if (attr is YAXDictionaryAttribute) { m_dictionaryAttributeInstance = attr as YAXDictionaryAttribute; } else if (attr is YAXErrorIfMissedAttribute) { var temp = attr as YAXErrorIfMissedAttribute; DefaultValue = temp.DefaultValue; TreatErrorsAs = temp.TreatAs; } else if (attr is YAXFormatAttribute) { Format = (attr as YAXFormatAttribute).Format; } else if (attr is YAXNotCollectionAttribute) { // arrays are always treated as collections if (!ReflectionUtils.IsArray(MemberType)) { IsAttributedAsNotCollection = true; } } else if (attr is YAXCustomSerializerAttribute) { Type serType = (attr as YAXCustomSerializerAttribute).CustomSerializerType; Type genTypeArg; bool isDesiredInterface = ReflectionUtils.IsDerivedFromGenericInterfaceType(serType, typeof(ICustomSerializer <>), out genTypeArg); if (!isDesiredInterface) { throw new YAXException("The provided custom serialization type is not derived from the proper interface"); } else if (genTypeArg != this.MemberType) { throw new YAXException("The generic argument of the class and the member type do not match"); } else { CustomSerializerType = serType; } } else if (attr is YAXPreserveWhitespaceAttribute) { PreservesWhitespace = true; } else if (attr is YAXSerializableTypeAttribute) { // this should not happen throw new Exception("This attribute is not applicable to fields and properties!"); } else if (attr is YAXNamespaceAttribute) { var nsAttrib = (attr as YAXNamespaceAttribute); Namespace = nsAttrib.Namespace; NamespacePrefix = nsAttrib.Prefix; } else { throw new Exception("Added new attribute type to the library but not yet processed!"); } }
private object DeserializeTaggedDictionaryValue(XElement xelemValue, XName alias, Type type, YAXCollectionAttribute colAttributeInstance, YAXDictionaryAttribute dicAttrInstance) { // otherwise the "else if(member.IsTreatedAsCollection)" block solves the problem Type keyType, valueType; if (!ReflectionUtils.IsIDictionary(type, out keyType, out valueType)) { throw new Exception("elemValue must be a Dictionary"); } // deserialize non-collection fields var namespaceToOverride = alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone(); var containerSer = NewInternalSerializer(type, namespaceToOverride, null); containerSer.IsCraetedToDeserializeANonCollectionMember = true; containerSer.RemoveDeserializedXmlNodes = true; object dic = containerSer.DeserializeBase(xelemValue); FinalizeNewSerializer(containerSer, false); // now try to deserialize collection fields Type pairType = null; ReflectionUtils.IsIEnumerable(type, out pairType); XName eachElementName = StringUtils.RefineSingleElement(ReflectionUtils.GetTypeFriendlyName(pairType)); bool isKeyAttrib = false; bool isValueAttrib = false; bool isKeyContent = false; bool isValueContent = false; XName keyAlias = alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Key"; XName valueAlias = alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Value"; if (colAttributeInstance != null && colAttributeInstance.EachElementName != null) { eachElementName = StringUtils.RefineSingleElement(colAttributeInstance.EachElementName); eachElementName = eachElementName.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance != null) { if (dicAttrInstance.EachPairName != null) { eachElementName = StringUtils.RefineSingleElement(dicAttrInstance.EachPairName); eachElementName = eachElementName.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance.SerializeKeyAs == YAXNodeTypes.Attribute) { isKeyAttrib = ReflectionUtils.IsBasicType(keyType); } else if (dicAttrInstance.SerializeKeyAs == YAXNodeTypes.Content) { isKeyContent = ReflectionUtils.IsBasicType(keyType); } if (dicAttrInstance.SerializeValueAs == YAXNodeTypes.Attribute) { isValueAttrib = ReflectionUtils.IsBasicType(valueType); } else if (dicAttrInstance.SerializeValueAs == YAXNodeTypes.Content) { isValueContent = ReflectionUtils.IsBasicType(valueType); } if (dicAttrInstance.KeyName != null) { keyAlias = StringUtils.RefineSingleElement(dicAttrInstance.KeyName); keyAlias = keyAlias.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } if (dicAttrInstance.ValueName != null) { valueAlias = StringUtils.RefineSingleElement(dicAttrInstance.ValueName); valueAlias = valueAlias.OverrideNsIfEmpty(alias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone()); } } foreach (XElement childElem in xelemValue.Elements(eachElementName)) { object key = null, value = null; YAXSerializer keySer = null, valueSer = null; bool isKeyFound = VerifyDictionaryPairElements(ref keyType, ref isKeyAttrib, ref isKeyContent, keyAlias, childElem); bool isValueFound = VerifyDictionaryPairElements(ref valueType, ref isValueAttrib, ref isValueContent, valueAlias, childElem); if (!isKeyFound && !isValueFound) continue; if (isKeyFound) { if (isKeyAttrib) { key = ReflectionUtils.ConvertBasicType(childElem.Attribute_NamespaceSafe(keyAlias, m_documentDefaultNamespace).Value, keyType); } else if (isKeyContent) { key = ReflectionUtils.ConvertBasicType(childElem.GetXmlContent(), keyType); } else if (ReflectionUtils.IsBasicType(keyType)) { key = ReflectionUtils.ConvertBasicType(childElem.Element(keyAlias).Value, keyType); } else { if (keySer == null) keySer = NewInternalSerializer(keyType, keyAlias.Namespace, null); key = keySer.DeserializeBase(childElem.Element(keyAlias)); FinalizeNewSerializer(keySer, false); } } if (isValueFound) { if (isValueAttrib) { value = ReflectionUtils.ConvertBasicType(childElem.Attribute_NamespaceSafe(valueAlias, m_documentDefaultNamespace).Value, valueType); } else if (isValueContent) { value = ReflectionUtils.ConvertBasicType(childElem.GetXmlContent(), valueType); } else if (ReflectionUtils.IsBasicType(valueType)) { value = ReflectionUtils.ConvertBasicType(childElem.Element(valueAlias).Value, valueType); } else { if (valueSer == null) valueSer = NewInternalSerializer(valueType, valueAlias.Namespace, null); value = valueSer.DeserializeBase(childElem.Element(valueAlias)); FinalizeNewSerializer(valueSer, false); } } try { type.InvokeMember("Add", BindingFlags.InvokeMethod, null, dic, new object[] { key, value }); } catch { OnExceptionOccurred( new YAXCannotAddObjectToCollection(alias.LocalName, new KeyValuePair<object, object>(key, value)), m_defaultExceptionType); } } return dic; }