a wrapper class around user-defined types, for quick acess to their YAXLib related attributes
Example #1
0
        /// <summary>
        /// Adds the namespace applying to the object type specified in <paramref name="wrapper"/>
        /// to the <paramref name="className"/>
        /// </summary>
        /// <param name="wrapper">The wrapper around the object who's namespace should be added</param>
        /// <param name="className">The root node of the document to which the namespace should be written</param>
        private XElement CreateElementWithNamespace(UdtWrapper wrapper, XName className)
        {
            XName elemName = className.OverrideNsIfEmpty(wrapper.Namespace);
            if (elemName.Namespace == wrapper.Namespace)
                RegisterNamespace(elemName.Namespace, wrapper.NamespacePrefix);
            else
                RegisterNamespace(elemName.Namespace, null);

            return new XElement(elemName, null);
        }
Example #2
0
        /// <summary>
        /// The basic method which performs the whole job of deserialization.
        /// </summary>
        /// <param name="baseElement">The element to be deserialized.</param>
        /// <returns>object containing the deserialized data</returns>
        private object DeserializeBase(XElement baseElement)
        {
            if (baseElement == null)
            {
                return m_desObject;
            }

            if (m_udtWrapper.HasCustomSerializer)
            {
                return InvokeCustomDeserializerFromElement(m_udtWrapper.CustomSerializerType, baseElement);
            }

            var realTypeAttr = baseElement.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName);
            if (realTypeAttr != null)
            {
                Type theRealType = ReflectionUtils.GetTypeByName(realTypeAttr.Value);
                if (theRealType != null)
                {
                    m_type = theRealType;
                    m_udtWrapper = TypeWrappersPool.Pool.GetTypeWrapper(m_type, this);
                }
            }

            if (m_type.IsGenericType && m_type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
            {
                return DeserializeKeyValuePair(baseElement);
            }

            if (KnownTypes.IsKnowType(m_type))
            {
                return KnownTypes.Deserialize(baseElement, m_type, TypeNamespace);
            }

            if ((m_udtWrapper.IsTreatedAsCollection || m_udtWrapper.IsTreatedAsDictionary) && !IsCraetedToDeserializeANonCollectionMember)
            {
                if (m_udtWrapper.DictionaryAttributeInstance != null)
                {
                    return DeserializeTaggedDictionaryValue(baseElement, m_udtWrapper.Alias, m_type, m_udtWrapper.CollectionAttributeInstance, m_udtWrapper.DictionaryAttributeInstance);
                }
                else
                {
                    return DeserializeCollectionValue(m_type, baseElement, m_udtWrapper.Alias, m_udtWrapper.CollectionAttributeInstance);
                }
            }

            if (ReflectionUtils.IsBasicType(m_type))
            {
                return ReflectionUtils.ConvertBasicType(baseElement.Value, m_type);
            }

            object o = null;
            if (m_desObject != null)
                o = m_desObject;
            else
                o = m_type.InvokeMember(string.Empty, BindingFlags.CreateInstance, null, null, new object[0]);

            bool foundAnyOfMembers = false;
            foreach (var member in GetFieldsToBeSerialized())
            {
                if (!member.CanWrite)
                    continue;

                if (member.IsAttributedAsDontSerialize)
                    continue;

                // reset handled exceptions status
                m_exceptionOccurredDuringMemberDeserialization = false;

                string elemValue = string.Empty; // the element value gathered at the first phase
                XElement xelemValue = null; // the XElement instance gathered at the first phase
                XAttribute xattrValue = null; // the XAttribute instance gathered at the first phase

                // first evaluate elemValue
                bool createdFakeElement = false;

                var serializationLocation = member.SerializationLocation;

                if (member.IsSerializedAsAttribute)
                {

                    // find the parent element from its location
                    XAttribute attr = XMLUtils.FindAttribute(baseElement, serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace));
                    if (attr == null) // if the parent element does not exist
                    {
                        // loook for an element with the same name AND a yaxlib:realtype attribute
                        XElement elem = XMLUtils.FindElement(baseElement, serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace));
                        if (elem != null && elem.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName) != null)
                        {
                            elemValue = elem.Value;
                            xelemValue = elem;
                        }
                        else
                        {
                            this.OnExceptionOccurred(new YAXAttributeMissingException(
                                StringUtils.CombineLocationAndElementName(serializationLocation, member.Alias)),
                                (!member.MemberType.IsValueType && m_udtWrapper.IsNotAllowdNullObjectSerialization) ? YAXExceptionTypes.Ignore : member.TreatErrorsAs);
                        }
                    }
                    else
                    {
                        foundAnyOfMembers = true;
                        elemValue = attr.Value;
                        xattrValue = attr;
                    }
                }
                else if (member.IsSerializedAsValue)
                {
                    XElement elem = XMLUtils.FindLocation(baseElement, serializationLocation);
                    if (elem == null) // such element is not found
                    {
                        this.OnExceptionOccurred(new YAXElementMissingException(
                                serializationLocation),
                                (!member.MemberType.IsValueType && m_udtWrapper.IsNotAllowdNullObjectSerialization) ? YAXExceptionTypes.Ignore : member.TreatErrorsAs);
                    }
                    else
                    {
                        XText[] values = elem.Nodes().OfType<XText>().ToArray();
                        if(values.Length <= 0)
                        {
                            // loook for an element with the same name AND a yaxlib:realtype attribute
                            XElement innerelem = XMLUtils.FindElement(baseElement, serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace));
                            if (innerelem != null && innerelem.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName) != null)
                            {
                                elemValue = innerelem.Value;
                                xelemValue = innerelem;
                            }
                            else
                            {
                                this.OnExceptionOccurred(new YAXElementValueMissingException(serializationLocation),
                                    (!member.MemberType.IsValueType && m_udtWrapper.IsNotAllowdNullObjectSerialization) ? YAXExceptionTypes.Ignore : member.TreatErrorsAs);
                            }
                        }
                        else
                        {
                            foundAnyOfMembers = true;
                            elemValue = values[0].Value;
                            values[0].Remove();
                        }
                    }
                }
                else // if member is serialized as an xml element
                {
                    bool canContinue = false;
                    XElement elem = XMLUtils.FindElement(baseElement, serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace));
                    if (elem == null) // such element is not found
                    {
                        if ((member.IsTreatedAsCollection || member.IsTreatedAsDictionary) && member.CollectionAttributeInstance != null &&
                            member.CollectionAttributeInstance.SerializationType == YAXCollectionSerializationTypes.RecursiveWithNoContainingElement)
                        {
                            if (AtLeastOneOfCollectionMembersExists(baseElement, member))
                            {
                                elem = baseElement;
                                canContinue = true;
                                foundAnyOfMembers = true;
                            }
                            else
                            {
                                member.SetValue(o, member.DefaultValue);
                                continue;
                            }
                        }
                        else if (!ReflectionUtils.IsBasicType(member.MemberType) && !member.IsTreatedAsCollection && !member.IsTreatedAsDictionary)
                        {
                            // try to fix this problem by creating a fake element, maybe all its children are placed somewhere else
                            XElement fakeElem = XMLUtils.CreateElement(baseElement, serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace));
                            if (fakeElem != null)
                            {
                                createdFakeElement = true;
                                if (AtLeastOneOfMembersExists(fakeElem, member.MemberType))
                                {
                                    canContinue = true;
                                    foundAnyOfMembers = true;
                                    elem = fakeElem;
                                    elemValue = elem.Value;
                                }
                            }
                        }

                        if (!canContinue)
                        {
                            this.OnExceptionOccurred(new YAXElementMissingException(
                                StringUtils.CombineLocationAndElementName(serializationLocation, member.Alias.OverrideNsIfEmpty(TypeNamespace))),
                                (!member.MemberType.IsValueType && m_udtWrapper.IsNotAllowdNullObjectSerialization) ? YAXExceptionTypes.Ignore : member.TreatErrorsAs);
                        }
                    }
                    else
                    {
                        foundAnyOfMembers = true;
                        elemValue = elem.Value;
                    }

                    xelemValue = elem;
                }

                // Phase2: Now try to retrieve elemValue's value, based on values gathered in xelemValue, xattrValue, and elemValue
                if (m_exceptionOccurredDuringMemberDeserialization)
                {
                    if (m_desObject == null) // i.e. if it was NOT resuming deserialization, set default value, otherwise existing value for the member is kept
                    {
                        if (!member.MemberType.IsValueType && m_udtWrapper.IsNotAllowdNullObjectSerialization)
                        {
                            try
                            {
                                member.SetValue(o, null);
                            }
                            catch
                            {
                                OnExceptionOccurred(
                                    new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue),
                                    m_defaultExceptionType);
                            }
                        }
                        else if (member.DefaultValue != null)
                        {
                            try
                            {
                                member.SetValue(o, member.DefaultValue);
                            }
                            catch
                            {
                                OnExceptionOccurred(
                                    new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue),
                                    m_defaultExceptionType);
                            }
                        }
                        else
                        {
                            if (!member.MemberType.IsValueType)
                            {
                                member.SetValue(o, null /*the value to be assigned */);
                            }
                        }
                    }
                }
                else if (member.HasCustomSerializer || member.MemberTypeWrapper.HasCustomSerializer)
                {
                    Type deserType = member.HasCustomSerializer ?
                        member.CustomSerializerType :
                        member.MemberTypeWrapper.CustomSerializerType;

                    object desObj;
                    if (member.IsSerializedAsAttribute)
                    {
                        desObj = InvokeCustomDeserializerFromAttribute(deserType, xattrValue);
                    }
                    else if (member.IsSerializedAsElement)
                    {
                        desObj = InvokeCustomDeserializerFromElement(deserType, xelemValue);
                    }
                    else if (member.IsSerializedAsValue)
                    {
                        desObj = InvokeCustomDeserializerFromValue(deserType, elemValue);
                    }
                    else
                    {
                        throw new Exception("unknown situation");
                    }

                    try
                    {
                        member.SetValue(o, desObj);
                    }
                    catch
                    {
                        OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType);
                    }
                }
                else if (elemValue != null)
                {
                    RetreiveElementValue(o, member, elemValue, xelemValue);
                    if (createdFakeElement && !m_exceptionOccurredDuringMemberDeserialization)
                        foundAnyOfMembers = true;
                }

                if (createdFakeElement && xelemValue != null)
                {
                    // remove the fake element
                    xelemValue.Remove();
                }
            }

            // if an empty element was given and non of its members have been retreived then return null, not an instance
            if (!foundAnyOfMembers && !baseElement.HasElements && !baseElement.HasAttributes && baseElement.IsEmpty)
                return null;

            return o;
        }
Example #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="YAXSerializer"/> class.
 /// </summary>
 /// <param name="t">The type of the object being serialized/deserialized.</param>
 /// <param name="exceptionPolicy">The exception handling policy.</param>
 /// <param name="defaultExType">The exceptions are treated as the value specified, unless otherwise specified.</param>
 /// <param name="option">The serialization option.</param>
 public YAXSerializer(Type t, YAXExceptionHandlingPolicies exceptionPolicy, YAXExceptionTypes defaultExType, YAXSerializationOptions option)
 {
     m_type = t;
     m_exceptionPolicy = exceptionPolicy;
     m_defaultExceptionType = defaultExType;
     m_serializationOption = option;
     // this must be the last call
     m_udtWrapper = TypeWrappersPool.Pool.GetTypeWrapper(m_type, this);
     if (m_udtWrapper.HasNamespace)
         TypeNamespace = m_udtWrapper.Namespace;
 }
Example #4
0
 /// <summary>
 /// Gets the sequence of fields to be serialized for the specified type. This sequence is retreived according to 
 /// the field-types specified by the user.
 /// </summary>
 /// <param name="typeWrapper">The type wrapper for the type whose serializable 
 /// fields is going to be retreived.</param>
 /// <returns>the sequence of fields to be serialized for the specified type</returns>
 private IEnumerable<MemberWrapper> GetFieldsToBeSerialized(UdtWrapper typeWrapper)
 {
     foreach (var member in typeWrapper.UnderlyingType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
     {
         char name0 = member.Name[0];
         if ((Char.IsLetter(name0) || name0 == '_') &&
             (member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field))
         {
             MemberWrapper memInfo = new MemberWrapper(member, this);
             if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize))
             {
                 yield return memInfo;
             }
         }
     }
 }
Example #5
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 = 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);

            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(false))
            {
                // no need to preces, it has been proccessed earlier
                if (attrsToProcessEarlier.Contains(attr.GetType()))
                    continue;
                //if (attr is YAXCustomSerializerAttribute)
                //    continue; // no need to preces, it has been proccessed earlier

                if (attr is YAXBaseAttribute)
                    ProcessYaxAttribute(attr);
            }
        }
Example #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)
        {
            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;
        }
Example #7
0
        public void TestWrappers()
        {
            var typeToTest = typeof (Guid);
            var serializer = new YAXSerializer(typeToTest);
            var typeWrapper = new UdtWrapper(typeToTest, serializer);

            Assert.IsTrue(typeWrapper.IsKnownType);
        }
Example #8
0
        /// <summary>
        /// Gets the type wrapper corresponding to the specified type.
        /// </summary>
        /// <param name="t">The type whose wrapper is needed.</param>
        /// <param name="caller">reference to the serializer instance which called this method.</param>
        /// <returns>the type wrapper corresponding to the specified type</returns>
        public UdtWrapper GetTypeWrapper(Type t, YAXSerializer caller)
        {
            lock (m_lockDic)
            {
                UdtWrapper result;
                if (!m_dicTypes.TryGetValue(t, out result))
                {
                    result = new UdtWrapper(t, caller);
                    m_dicTypes.Add(t, result);
                }
                else
                {
                    result.SetYAXSerializerOptions(caller);
                }

                return result;
            }
        }
Example #9
0
        /// <summary>
        /// Gets the sequence of fields to be serialized for the specified type. This sequence is retreived according to 
        /// the field-types specified by the user.
        /// </summary>
        /// <param name="typeWrapper">The type wrapper for the type whose serializable 
        /// fields is going to be retreived.</param>
        /// <returns>the sequence of fields to be serialized for the specified type</returns>
        private IEnumerable<MemberWrapper> GetFieldsToBeSerialized(UdtWrapper typeWrapper)
        {
            foreach (var member in typeWrapper.UnderlyingType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                char name0 = member.Name[0];
                if ((Char.IsLetter(name0) || name0 == '_') &&
                    (member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field))
                {
                    if((typeWrapper.IsCollectionType || typeWrapper.IsDictionaryType)) //&& typeWrapper.IsAttributedAsNotCollection)
                        if(ReflectionUtils.IsPartOfNetFx(member))
                            continue;

                    var memInfo = new MemberWrapper(member, this);
                    if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize))
                    {
                        yield return memInfo;
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// Gets the sequence of fields to be serialized for the specified type. This sequence is retreived according to 
        /// the field-types specified by the user.
        /// </summary>
        /// <param name="typeWrapper">The type wrapper for the type whose serializable 
        /// fields is going to be retreived.</param>
        /// <returns>the sequence of fields to be serialized for the specified type</returns>
        private IEnumerable<MemberWrapper> GetFieldsToBeSerialized(UdtWrapper typeWrapper)
        {
            foreach (var member in typeWrapper.UnderlyingType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                char name0 = member.Name[0];
                if ((Char.IsLetter(name0) || name0 == '_') && // TODO: this is wrong, .NET supports unicode variable names or those starting with @
                    (member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field))
                {
                    var prop = member as PropertyInfo;
                    if (prop != null)
                    {
                        // ignore indexers; if member is an indexer property, do not serialize it
                        if (prop.GetIndexParameters().Length > 0)
                            continue;

                        // don't serialize delegates as well
                        if (ReflectionUtils.IsTypeEqualOrInheritedFromType(prop.PropertyType, typeof(Delegate)))
                            continue;
                    }

                    if((typeWrapper.IsCollectionType || typeWrapper.IsDictionaryType)) //&& typeWrapper.IsAttributedAsNotCollection)
                        if(ReflectionUtils.IsPartOfNetFx(member))
                            continue;

                    var memInfo = new MemberWrapper(member, this);
                    if (memInfo.IsAllowedToBeSerialized(typeWrapper.FieldsToSerialize, m_udtWrapper.DontSerializePropertiesWithNoSetter))
                    {
                        yield return memInfo;
                    }
                }
            }
        }
Example #11
0
        public void TestWrappers()
        {
            var typeToTest = typeof (TimeSpan);
            var serializer = new YAXSerializer(typeToTest);
            var typeWrapper = new UdtWrapper(typeToTest, serializer);

            Assert.That(typeWrapper.IsKnownType, Is.True);
        }