예제 #1
0
        /// <summary>
        /// Retreives the collection value.
        /// </summary>
        /// <param name="colType">Type of the collection to be retrieved.</param>
        /// <param name="xelemValue">The value of xml element.</param>
        /// <param name="memberAlias">The member's alias, used only in exception titles.</param>
        /// <param name="colAttrInstance">The collection attribute instance.</param>
        /// <returns></returns>
        private object DeserializeCollectionValue(Type colType, XElement xelemValue, XName memberAlias, YAXCollectionAttribute colAttrInstance)
        {
            object containerObj = null;
            if (ReflectionUtils.IsInstantiableCollection(colType))
            {
                var containerSer = new YAXSerializer(colType, m_exceptionPolicy, m_defaultExceptionType,
                                                     m_serializationOption);
                containerSer.m_documentDefaultNamespace = m_documentDefaultNamespace;
                containerSer.SetNamespaceToOverrideEmptyNamespace(
                    memberAlias.Namespace.
                        IfEmptyThen(TypeNamespace).
                        IfEmptyThenNone());

                containerSer.IsCraetedToDeserializeANonCollectionMember = true;
                containerSer.RemoveDeserializedXmlNodes = true;

                containerObj = containerSer.DeserializeBase(xelemValue);
                m_parsingErrors.AddRange(containerSer.ParsingErrors);
            }

            var lst = new List<object>(); // this will hold the actual data items
            Type itemType = ReflectionUtils.GetCollectionItemType(colType);

            if (ReflectionUtils.IsBasicType(itemType) && colAttrInstance != null && colAttrInstance.SerializationType == YAXCollectionSerializationTypes.Serially)
            {
                // What if the collection was serialized serially
                char[] seps = colAttrInstance.SeparateBy.ToCharArray();

                // can white space characters be added to the separators?
                if (colAttrInstance.IsWhiteSpaceSeparator)
                {
                    seps = seps.Union(new [] { ' ', '\t', '\r', '\n' }).ToArray();
                }

                string elemValue = xelemValue.Value;
                string[] items = elemValue.Split(seps, StringSplitOptions.RemoveEmptyEntries);

                foreach (string wordItem in items)
                {
                    try
                    {
                        lst.Add(ReflectionUtils.ConvertBasicType(wordItem, itemType));
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXBadlyFormedInput(memberAlias.ToString(), elemValue), m_defaultExceptionType);
                    }
                }
            }
            else //if the collection was serialized recursively
            {
                bool isPrimitive = ReflectionUtils.IsBasicType(itemType);

                XName eachElemName = null;
                if (colAttrInstance != null && colAttrInstance.EachElementName != null)
                {
                    eachElemName = StringUtils.RefineSingleElement(colAttrInstance.EachElementName);
                    eachElemName = eachElemName.OverrideNsIfEmpty(memberAlias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
                }

                var elemsToSearch = eachElemName == null ? xelemValue.Elements() : xelemValue.Elements(eachElemName);

                foreach (XElement childElem in elemsToSearch)
                {
                    Type curElementType = itemType;
                    bool curElementIsPrimitive = isPrimitive;

                    XAttribute realTypeAttribute = childElem.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, m_documentDefaultNamespace);
                    if (realTypeAttribute != null)
                    {
                        Type theRealType = ReflectionUtils.GetTypeByName(realTypeAttribute.Value);
                        if (theRealType != null)
                        {
                            curElementType = theRealType;
                            curElementIsPrimitive = ReflectionUtils.IsBasicType(curElementType);
                        }
                    }

                    // TODO: check if curElementType is derived or is the same is itemType, for speed concerns perform this check only when elementName is null
                    if (eachElemName == null && (curElementType == typeof(object) || !ReflectionUtils.IsTypeEqualOrInheritedFromType(curElementType, itemType)))
                        continue;

                    if (curElementIsPrimitive)
                    {
                        try
                        {
                            lst.Add(ReflectionUtils.ConvertBasicType(childElem.Value, curElementType));
                        }
                        catch
                        {
                            OnExceptionOccurred(new YAXBadlyFormedInput(childElem.Name.ToString(), childElem.Value), m_defaultExceptionType);
                        }
                    }
                    else
                    {
                        var ser = new YAXSerializer(curElementType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
                        ser.m_documentDefaultNamespace = m_documentDefaultNamespace;
                        ser.SetNamespaceToOverrideEmptyNamespace(
                            memberAlias.Namespace.
                                IfEmptyThen(TypeNamespace).
                                IfEmptyThenNone());

                        lst.Add(ser.DeserializeBase(childElem));
                        m_parsingErrors.AddRange(ser.ParsingErrors);
                    }
                }
            } // end of else if 

            // Now what should I do with the filled list: lst
            Type dicKeyType, dicValueType;
            if (ReflectionUtils.IsArray(colType))
            {
                XAttribute dimsAttr = xelemValue.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_dimsAttrName, m_documentDefaultNamespace);
                int[] dims = new int[0];
                if (dimsAttr != null)
                {
                    dims = StringUtils.ParseArrayDimsString(dimsAttr.Value);
                }

                Array arrayInstance = null;
                if (dims.Length > 0)
                {
                    var lowerBounds = new int[dims.Length]; // an array of zeros
                    arrayInstance = Array.CreateInstance(itemType, dims, lowerBounds); // create the array

                    int count = Math.Min(arrayInstance.Length, lst.Count);
                    // now fill the array
                    for (int i = 0; i < count; i++)
                    {
                        int[] inds = GetArrayDimentionalIndex(i, dims);
                        try
                        {
                            arrayInstance.SetValue(lst[i], inds);
                        }
                        catch
                        {
                            OnExceptionOccurred(
                                new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]),
                                m_defaultExceptionType);
                        }
                    }
                }
                else
                {
                    arrayInstance = Array.CreateInstance(itemType, lst.Count); // create the array

                    int count = Math.Min(arrayInstance.Length, lst.Count);
                    // now fill the array
                    for (int i = 0; i < count; i++)
                    {
                        try
                        {
                            arrayInstance.SetValue(lst[i], i);
                        }
                        catch
                        {
                            OnExceptionOccurred(
                                new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]),
                                m_defaultExceptionType);
                        }
                    }
                }

                return arrayInstance;
            }
            else if (ReflectionUtils.IsIDictionary(colType, out dicKeyType, out dicValueType))
            {
                //The collection is a Dictionary
                object dic = containerObj;

                foreach (var lstItem in lst)
                {
                    object key = itemType.GetProperty("Key").GetValue(lstItem, null);
                    object value = itemType.GetProperty("Value").GetValue(lstItem, null);
                    try
                    {
                        colType.InvokeMember("Add", BindingFlags.InvokeMethod, null, dic, new[] { key, value });
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), m_defaultExceptionType);
                    }
                }

                return dic;
            }
            else if (ReflectionUtils.IsNonGenericIDictionary(colType))
            {
                object col = containerObj;
                foreach (var lstItem in lst)
                {
                    object key = lstItem.GetType().GetProperty("Key", BindingFlags.Instance | BindingFlags.Public).GetValue(lstItem, null);
                    object value = lstItem.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public).GetValue(lstItem, null);

                    try
                    {
                        colType.InvokeMember("Add", BindingFlags.InvokeMethod, null, col, new[] { key, value });
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), m_defaultExceptionType);
                    }
                }

                return col;
            }
            else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(BitArray)))
            {
                var bArray = new bool[lst.Count];
                for (int i = 0; i < bArray.Length; i++)
                {
                    try
                    {
                        bArray[i] = (bool)lst[i];
                    }
                    catch
                    {
                    }
                }

                object col = colType.InvokeMember(string.Empty, System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { bArray });

                return col;
            }
            else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Stack)) ||
                ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Stack<>)))
            {
                //object col = colType.InvokeMember(string.Empty, System.Reflection.BindingFlags.CreateInstance, null, null, new object[0]);
                object col = containerObj;

                const string additionMethodName = "Push";

                for (int i = lst.Count - 1; i >= 0; i--) // the loop must be from end to front
                {
                    try
                    {
                        colType.InvokeMember(additionMethodName, BindingFlags.InvokeMethod, null, col, new[] { lst[i] });
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]), m_defaultExceptionType);
                    }
                }

                return col;
            }
            else if (ReflectionUtils.IsIEnumerable(colType))
            {
                if (containerObj == null)
                    return lst;

                object col = containerObj;

                string additionMethodName = "Add";

                if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Queue)) ||
                    ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Queue<>)))
                {
                    additionMethodName = "Enqueue";
                }
                else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(LinkedList<>)))
                {
                    additionMethodName = "AddLast";
                }

                foreach (var lstItem in lst)
                {
                    try
                    {
                        colType.InvokeMember(additionMethodName, BindingFlags.InvokeMethod, null, col, new object[] { lstItem });
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), this.m_defaultExceptionType);
                    }
                }

                return col;
            }

            return null;
        }
예제 #2
0
        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 containerSer = new YAXSerializer(type, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
            containerSer.m_documentDefaultNamespace = m_documentDefaultNamespace;
            containerSer.SetNamespaceToOverrideEmptyNamespace(
                alias.Namespace.
                    IfEmptyThen(TypeNamespace).
                    IfEmptyThenNone());

            containerSer.IsCraetedToDeserializeANonCollectionMember = true;
            containerSer.RemoveDeserializedXmlNodes = true;
            object dic = containerSer.DeserializeBase(xelemValue);
            m_parsingErrors.AddRange(containerSer.ParsingErrors);

            // 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 = new YAXSerializer(keyType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
                            keySer.m_documentDefaultNamespace = m_documentDefaultNamespace;
                            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, 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 = new YAXSerializer(valueType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
                            valueSer.m_documentDefaultNamespace = m_documentDefaultNamespace;
                            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
                {
                    OnExceptionOccurred(
                        new YAXCannotAddObjectToCollection(alias.LocalName, new KeyValuePair<object, object>(key, value)),
                        m_defaultExceptionType);
                }
            }

            return dic;
        }
예제 #3
0
        /// <summary>
        /// Serializes a collection object.
        /// </summary>
        /// <param name="insertionLocation">The insertion location.</param>
        /// <param name="elementName">Name of the element.</param>
        /// <param name="elementValue">The object to be serailized.</param>
        /// <param name="collectionAttrInst">The collection attribute instance.</param>
        /// <param name="format">formatting string, which is going to be applied to all members of the collection.</param>
        /// <returns>
        /// an instance of <c>XElement</c> which will contain the serailized collection
        /// </returns>
        private XElement MakeCollectionElement(
            XElement insertionLocation, XName elementName, object elementValue,
            YAXCollectionAttribute collectionAttrInst, string format)
        {
            if (elementValue == null)
            {
                return new XElement(elementName);
            }

            if (!(elementValue is IEnumerable))
            {
                throw new ArgumentException("elementValue must be an IEnumerable");
            }

            // serialize other non-collection members
            var ser = new YAXSerializer(elementValue.GetType(), m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
            ser.m_documentDefaultNamespace = m_documentDefaultNamespace;
            ser.SetNamespaceToOverrideEmptyNamespace(elementName.Namespace);
            ser.SetBaseElement(insertionLocation);
            XElement elemToAdd = ser.SerializeBase(elementValue, elementName);
            ImportNamespaces(ser);
            m_parsingErrors.AddRange(ser.ParsingErrors);

            // now iterate through collection members

            var collectionInst = elementValue as IEnumerable;
            var serType = YAXCollectionSerializationTypes.Recursive;
            string seperator = string.Empty;
            XName eachElementName = null;

            if (collectionAttrInst != null)
            {
                serType = collectionAttrInst.SerializationType;
                seperator = collectionAttrInst.SeparateBy;
                if (collectionAttrInst.EachElementName != null)
                {
                    eachElementName = StringUtils.RefineSingleElement(collectionAttrInst.EachElementName);
                    if (eachElementName.Namespace.IsEmpty())
                        RegisterNamespace(eachElementName.Namespace, null);
                    eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
                }
            }

            Type colItemType = ReflectionUtils.GetCollectionItemType(elementValue.GetType());

            if (serType == YAXCollectionSerializationTypes.Serially && !ReflectionUtils.IsBasicType(colItemType))
                serType = YAXCollectionSerializationTypes.Recursive;

            UdtWrapper colItemsUdt = TypeWrappersPool.Pool.GetTypeWrapper(colItemType, this);

            if (serType == YAXCollectionSerializationTypes.Serially && elemToAdd.IsEmpty)
            {
                var sb = new StringBuilder();

                bool isFirst = true;
                object objToAdd = null;
                foreach (object obj in collectionInst)
                {
                    if (colItemsUdt.IsEnum)
                        objToAdd = colItemsUdt.EnumWrapper.GetAlias(obj);
                    else if (format != null)
                        objToAdd = ReflectionUtils.TryFormatObject(obj, format);
                    else
                        objToAdd = obj;

                    if (isFirst)
                    {
                        sb.Append(objToAdd.ToXmlValue());
                        isFirst = false;
                    }
                    else
                    {
                        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", seperator, objToAdd);
                    }
                }

                bool alreadyAdded = false;
                elemToAdd = MakeBaseElement(insertionLocation, elementName, sb.ToString(), out alreadyAdded);
                if (alreadyAdded)
                    elemToAdd = null;
            }
            else
            {
                //var elem = new XElement(elementName, null);
                object objToAdd = null;

                foreach (object obj in collectionInst)
                {
                    objToAdd = (format == null) ? obj : ReflectionUtils.TryFormatObject(obj, format);
                    var curElemName = eachElementName;
                    
                    if(curElemName == null)
                    {
                        UdtWrapper udt = TypeWrappersPool.Pool.GetTypeWrapper(obj.GetType(), this);
                        curElemName = udt.Alias;
                    }

                    XElement itemElem = this.AddObjectToElement(elemToAdd, curElemName.OverrideNsIfEmpty(elementName.Namespace), objToAdd);
                    if (!obj.GetType().EqualsOrIsNullableOf(colItemType))
                    {
                        itemElem.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, obj.GetType().FullName, m_documentDefaultNamespace);
                        if (itemElem.Parent == null) // i.e., it has been removed, e.g., because all its members have been serialized outside the element
                            elemToAdd.Add(itemElem); // return it back, or undelete this item

                        RegisterYaxLibNamespace();
                    }
                }
            }

            int[] arrayDims = ReflectionUtils.GetArrayDimensions(elementValue);
            if (arrayDims != null && arrayDims.Length > 1)
            {
                elemToAdd.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_dimsAttrName, StringUtils.GetArrayDimsString(arrayDims), m_documentDefaultNamespace);
                RegisterYaxLibNamespace();
            }

            return elemToAdd;
        }
예제 #4
0
        /// <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);
            }

            Type keyType, valueType;
            if (!ReflectionUtils.IsIDictionary(elementValue.GetType(), out keyType, out valueType))
            {
                throw new ArgumentException("elementValue must be a Dictionary");
            }

            // serialize other non-collection members
            var ser = new YAXSerializer(elementValue.GetType(), m_exceptionPolicy, m_defaultExceptionType, m_serializationOption);
            ser.m_documentDefaultNamespace = m_documentDefaultNamespace;
            ser.SetNamespaceToOverrideEmptyNamespace(elementName.Namespace);
            ser.SetBaseElement(insertionLocation);
            XElement elem = ser.SerializeBase(elementValue, elementName);
            ImportNamespaces(ser);
            m_parsingErrors.AddRange(ser.ParsingErrors);

            // now iterate through collection members

            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.IsEmpty())
                    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.IsEmpty())
                        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.IsEmpty())
                    RegisterNamespace(keyAlias.Namespace, null);
                keyAlias = keyAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());

                valueAlias = StringUtils.RefineSingleElement(dicAttrInst.ValueName ?? "Value");
                if (valueAlias.Namespace.IsEmpty())
                    RegisterNamespace(valueAlias.Namespace, null);
                valueAlias = valueAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
            }

            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());
                }

                var elemChild = new XElement(eachElementName, null);

                if (isKeyAttrib && areKeyOfSameType)
                {
                    elemChild.AddAttributeNamespaceSafe(keyAlias, keyObj, m_documentDefaultNamespace);
                }
                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, m_documentDefaultNamespace);
                        RegisterYaxLibNamespace();
                    }
                }

                if (isValueAttrib && areValueOfSameType)
                {
                    elemChild.AddAttributeNamespaceSafe(valueAlias, valueObj, m_documentDefaultNamespace);
                }
                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, m_documentDefaultNamespace);
                        RegisterYaxLibNamespace();
                    }
                }

                elem.Add(elemChild);
            }

            return elem;
        }
예제 #5
0
        /// <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!");
            }
        }
예제 #6
0
        /// <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)
        {
            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 = m_memberInfo.GetCustomAttributes(attrType, true);
                foreach (var attr in customSerAttrs)
                {
                    ProcessYaxAttribute(attr);
                }
            }

            foreach (var attr in m_memberInfo.GetCustomAttributes(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;
        }
예제 #7
0
        /// <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!");
            }
        }