Ejemplo n.º 1
0
        public XDocument SerializeToXDocument(object obj)
        {
            XDocument xdoc = new XDocument();

            string defaultNamespace = DataContractSerializer_Helpers.GetDefaultNamespace(_type.Namespace, _useXmlSerializerFormat);

            //todo: USEMETHODTOGETTYPE: make a method that returns the actual type of object and replace all USEMETHODTOGETTYPE with a call to this method. (also find other places where we could use it)
            Type objectType = obj.GetType();

            if (obj is char) //special case because JSIL thinks a variable of type object containing a char contains a string.
            {
                objectType = typeof(char);
            }

            TypeInformation typeInformation = null;

            if (objectType != _type)
            {
                // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
                typeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(_type, defaultNamespace, _useXmlSerializerFormat);
            }

            // Add the root:
            List <XObject> xnodesForRoot = DataContractSerializer_Serialization.SerializeToXObjects(obj, _type, _knownTypes, _useXmlSerializerFormat, isRoot: true, isContainedInsideEnumerable: false, parentTypeInformation: typeInformation, nodeDefaultNamespaceIfAny: null);

            xdoc.Add(xnodesForRoot.First());
            return(xdoc);
        }
Ejemplo n.º 2
0
        public string SerializeToString(object obj, bool indentXml = false)
        {
            XDocument xdoc = new XDocument();

            string defaultNamespace = DataContractSerializer_Helpers.DATACONTRACTSERIALIZER_OBJECT_DEFAULT_NAMESPACE + _type.Namespace;

            //todo: USEMETHODTOGETTYPE: make a method that returns the actual type of object and replace all USEMETHODTOGETTYPE with a call to this method. (also find other places where we could use it)
            Type objectType = obj.GetType();

            if (obj is char) //special case because JSIL thinks a variable of type object containing a char contains a string.
            {
                objectType = typeof(char);
            }

            TypeInformation typeInformation = null;

            if (objectType != _type)
            {
                // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
                typeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(_type, defaultNamespace);
            }

            // Add the root:
            List <XNode> xnodesForRoot = DataContractSerializer_Serialization.SerializeToXNodes(obj, _type, _knownTypes, _useXmlSerializerFormat, isRoot: true, isContainedInsideEnumerable: false, parentTypeInformation: typeInformation, nodeDefaultNamespaceIfAny: null);

            xdoc.Add(xnodesForRoot.First());
            string xml = xdoc.ToString(indentXml);

            // Add the header:
            xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>" + Environment.NewLine + xml;

            return(xml);
        }
Ejemplo n.º 3
0
        static bool IsTypeSameAsTheOneSpecifiedInXmlTypeAttribute(Type typeToCompare, string typeNameInXmlTypeAttribute, string typeNamespaceInXmlTypeAttribute, bool useXmlSerializerFormat)
        {
            TypeInformation referenceTypeInfo = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(typeToCompare, null, useXmlSerializerFormat);
            string          typeNamespaceName = referenceTypeInfo.NamespaceName;
            string          typeName          = referenceTypeInfo.Name;

            // Compare the KnownType with the type name and namespace that we are looking for:
            if (typeName == typeNameInXmlTypeAttribute &&
                typeNamespaceName == typeNamespaceInXmlTypeAttribute)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        static bool IsTypeSameAsTheOneSpecifiedInXmlTypeAttribute(Type typeToCompare, string typeNameInXmlTypeAttribute, string typeNamespaceInXmlTypeAttribute)
        {
            string typeName = DataContractSerializer_Helpers.GetTypeNameSafeForSerialization(typeToCompare);

            string typeNamespaceName = DataContractSerializer_Helpers.DATACONTRACTSERIALIZER_OBJECT_DEFAULT_NAMESPACE + typeToCompare.Namespace;
            //todo: verify that the namespace is OK or if we should get the namespace specified by the DataContract attribute by calling "GetTypeInformationByReadingAttributes".
            TypeInformation referenceTypeInfo = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(typeToCompare, null);

            typeNamespaceName = referenceTypeInfo.NamespaceName;
            typeName          = referenceTypeInfo.Name;

            // Compare the KnownType with the type name and namespace that we are looking for:
            if (typeName == typeNameInXmlTypeAttribute &&
                typeNamespaceName == typeNamespaceInXmlTypeAttribute)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 5
0
        static List <XNode> SerializeToXNodes_Object_WithRecursion(object obj, Type objectType, Type resultExpectedType, IReadOnlyList <Type> knownTypes, bool useXmlSerializerFormat, string nodeDefaultNamespaceIfAny, bool isRoot, bool isContainedInsideEnumerable, TypeInformation parentTypeInformation)
        {
            // Call the "OnSerializing" method if any:
            CallOnSerializingMethod(obj, objectType);

            // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
            TypeInformation typeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(objectType, nodeDefaultNamespaceIfAny);

            // Process each member of the object:
            List <XNode> childrenNodes = new List <XNode>();
            IEnumerable <MemberInformationAndValue> membersAndValues = DataContractSerializer_Helpers.GetDataContractMembersAndValues(obj, serializationType: typeInformation.serializationType, useXmlSerializerFormat: useXmlSerializerFormat); //todo: normally, checking if a data contract is present is not enough to know if the type if "marked with attributes". According to the MSND article "Using Data Contracts", we should check for any of the following attributes: "DataContractAttribute, SerializableAttribute, CollectionDataContractAttribute, or EnumMemberAttribute attributes, or marked as serializable by any other means (such as IXmlSerializable)". cf. https://msdn.microsoft.com/en-us/library/ms733127(v=vs.100).aspx

            foreach (MemberInformationAndValue memberInfoAndValue in membersAndValues)
            {
                //------------------------------------
                // Process each member of the object
                //------------------------------------

                // Get the member information:
                MemberInfo memberInfo  = memberInfoAndValue.MemberInformation.MemberInfo;
                object     memberValue = memberInfoAndValue.MemberValue;
                string     memberName  = memberInfoAndValue.MemberInformation.Name;

                // Create the XNode for the member:
                XName xnameForMember;
                if (objectType.FullName.StartsWith("System.Collections.Generic.KeyValuePair"))
                {
                    if (memberName == "key")
                    {
                        memberName = "Key";
                    }
                    else if (memberName == "value")
                    {
                        memberName = "Value";
                    }
                    xnameForMember = memberName;
                }
                else
                {
                    if (typeInformation.NamespaceName == null) //todo: make sure we want to use this typeInformation since it comes from the type that contains of the current member and not the member itself.
                    {
                        xnameForMember = memberName;
                    }
                    else
                    {
                        xnameForMember = XNamespace.Get(typeInformation.NamespaceName).GetName(memberName);
                    }
                }
                XElement xElementForMember = new XElement(xnameForMember);

                bool isNull = ((memberValue == null) || DataContractSerializer_Helpers.CheckIfObjectIsNullNullable(memberValue));

                if (!isNull)
                {
                    Type expectedType = memberInfoAndValue.MemberInformation.MemberType;
                    Type memberType   = memberValue.GetType();

                    // Work around JSIL issues:
                    if (memberValue is char && expectedType == typeof(char)) //Note: this test is required because JSIL thinks that object testobj = 'c'; testobj.GetType() should return System.String...
                    {
                        memberType = typeof(char);
                    }
                    else if (expectedType == typeof(double)) //Note: this test is required because, with JSIL, "GetType" on a double returns "int" instead of "double". //todo: see if other workarounds to JSIL bugs like this one are required.
                    {
                        memberType = typeof(double);
                    }
                    else if (expectedType == typeof(byte)) //same as above.
                    {
                        memberType = typeof(byte);
                    }
                    else if (expectedType == typeof(float)) //same as above.
                    {
                        memberType = typeof(float);
                    }

                    bool isValueEnumerableDifferentThanString = (memberValue is IEnumerable) && !(memberValue is string);

                    Type nonNullableMemberType = memberType;
                    if (memberType.FullName.StartsWith("System.Nullable`1"))
                    {
                        nonNullableMemberType = Nullable.GetUnderlyingType(memberType);
                    }
                    Type nonNullableExpectedType = expectedType;
                    if (expectedType.FullName.StartsWith("System.Nullable`1"))
                    {
                        nonNullableExpectedType = Nullable.GetUnderlyingType(expectedType);
                    }

                    if (nonNullableMemberType != nonNullableExpectedType && !isValueEnumerableDifferentThanString)
                    {
                        //we want to add a type attribute to be able to know when deserializing that this is another type that the property's
                        if (DataContractSerializer_ValueTypesHandler.TypesToNames.ContainsKey(nonNullableMemberType)) //todo: should we add the nullable versions?
                        {
                            string prefixForType = xElementForMember.GetPrefixOfNamespace("http://www.w3.org/2001/XMLSchema");
                            if (string.IsNullOrWhiteSpace(prefixForType))
                            {
                                //we need to create a prefix for that
                                //todo:see if it would be ok to use d2p1 like silverlight seems to do, and if so, replace the following with just that.

                                prefixForType = DataContractSerializer_Helpers.GenerateUniqueNamespacePrefixIfNeeded(xElementForMember, "http://www.w3.org/2001/XMLSchema");

                                //we can finally add the type attribute:
                                xElementForMember.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), prefixForType + ":" + DataContractSerializer_ValueTypesHandler.TypesToNames[nonNullableMemberType]));
                            }
                            else
                            {
                                xElementForMember.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), prefixForType + ":" + DataContractSerializer_ValueTypesHandler.TypesToNames[nonNullableMemberType]));
                            }
                        }
                        else
                        {
                            bool isTypeOk = DataContractSerializer_KnownTypes.CheckIfItIsAKnownType(obj, objectType, knownTypes, memberType);
                            if (isTypeOk)
                            {
                                if (memberType.IsEnum) //enums are a special case because JSIL is not capable of handling Custom attributes on them.
                                {
                                    xElementForMember.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), memberType.Name));
                                }
                                else
                                {
                                    string defaultNamespace = DataContractSerializer_Helpers.DATACONTRACTSERIALIZER_OBJECT_DEFAULT_NAMESPACE + memberType.Namespace;

                                    // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
                                    TypeInformation childTypeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(memberType, defaultNamespace);

                                    string prefixForTypeName = "";
                                    if (childTypeInformation.NamespaceName != null)                                                                                                            //when the namespaceName is null I guess it means we don't need something like type="sth:ChildTypeName" but type="ChildTypeName" is sufficient.
                                    {
                                        prefixForTypeName = DataContractSerializer_Helpers.GenerateUniqueNamespacePrefixIfNeeded(xElementForMember, childTypeInformation.NamespaceName) + ":"; // note: we added : directly because whenever we have a prefix, we have ':' right after.
                                    }

                                    xElementForMember.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), prefixForTypeName + childTypeInformation.Name));
                                }
                            }
                            else
                            {
                                string namespaceNameToPutInException = "";
                                if (typeInformation.NamespaceName != null)
                                {
                                    namespaceNameToPutInException = ":" + typeInformation.NamespaceName;
                                }
                                throw new SerializationException("Type \"" + memberType.FullName + "\" with data contract name \"" + memberType.Name + namespaceNameToPutInException + "\" is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.");
                            }
                        }
                    }

                    //********** RECURSION **********
                    List <XNode> xnodesForMemberValue = SerializeToXNodes(memberValue, memberType, knownTypes, useXmlSerializerFormat, isRoot: false, isContainedInsideEnumerable: false, parentTypeInformation: typeInformation, nodeDefaultNamespaceIfAny: typeInformation.NamespaceName);
                    foreach (XNode xnodeForMemberValue in xnodesForMemberValue) // Note: the collection usually contains only 1 node, but there may be multiple nodes if for example we are serializing an Enumerable.
                    {
                        xElementForMember.Add(xnodeForMemberValue);
                    }
                }
                else
                {
                    //------------------------------------
                    // The value of the member is "null"
                    //------------------------------------

                    XName nilName = XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("nil");
                    xElementForMember.Add(new XAttribute(nilName, "true"));
                }
                childrenNodes.Add(xElementForMember);
            }
            if (isRoot || isContainedInsideEnumerable)
            {
                //we add a XElement with the type name as its name.
                //we create the XName for the node containing the type.

                //----------------------------------
                // Determine the name of the object to use in the XML:
                //----------------------------------

                //we get the type expected by the parent Enumerable:
                Type typeExpectedByParentEnumerable = isRoot ? resultExpectedType : DataContractSerializer_Helpers.GetInterface(parentTypeInformation.Type, "IEnumerable`1").GetGenericArguments()[0];

                string objectTypeName;

                // If the parent of the object is a collection that has the
                // "CollectionDataContractAttribute", we use the name specified
                // by that attribute, if any. Otherwise we determine the name
                // from the Type of the object

                if (parentTypeInformation != null &&
                    !string.IsNullOrEmpty(parentTypeInformation.ItemName))
                {
                    objectTypeName = parentTypeInformation.ItemName;
                }
                else
                {
                    objectTypeName = DataContractSerializer_Helpers.GetTypeNameSafeForSerialization(typeExpectedByParentEnumerable); // Note: in case of nested types, this method replaces the '+' with '.', and does other changes to obtain the type name to use in the serialization.
                }

                XName elementName;
                if (typeInformation.NamespaceName == null)
                {
                    elementName = objectTypeName;
                }
                else
                {
                    elementName = XNamespace.Get(typeInformation.NamespaceName).GetName(objectTypeName);
                }

                XElement xelement = new XElement(elementName);

                if (objectType.IsEnum) //enums are a special case because JSIL is not capable of handling Custom attributes on them.
                {
                    xelement.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), objectTypeName));
                }
                else if (typeInformation.NamespaceName != null && !objectType.IsGenericType && typeExpectedByParentEnumerable != obj.GetType())
                {
                    string prefixForTypeName = DataContractSerializer_Helpers.GenerateUniqueNamespacePrefixIfNeeded(xelement, typeInformation.NamespaceName);

                    xelement.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE).GetName("type"), prefixForTypeName + ":" + typeInformation.Name));
                }

                foreach (XNode node in childrenNodes)
                {
                    xelement.Add(node);
                }
                childrenNodes = new List <XNode>()
                {
                    xelement
                };
            }

            // Call the "OnSerialized" method if any:
            CallOnSerializedMethod(obj, objectType);

            return(childrenNodes);
        }
Ejemplo n.º 6
0
        static List <XNode> SerializeToXNodes_Enumerable_WithRecursion(object obj, Type objectType, IReadOnlyList <Type> knownTypes, bool useXmlSerializerFormat, string nodeDefaultNamespaceIfAny, bool isRoot, bool isContainedInsideEnumerable)
        {
            List <XNode> result = new List <XNode>();

            // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
            TypeInformation typeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(objectType, nodeDefaultNamespaceIfAny);

            // Traverse the collection:
            foreach (object item in (IEnumerable)obj)
            {
                //todo: USEMETHODTOGETTYPE: make a method that returns the actual type of object and replace all USEMETHODTOGETTYPE with a call to this method. (also find other places where we could use it)
                Type itemType = item.GetType();

                if (item is char) //special case because JSIL thinks a variable of type object containing a char contains a string.
                {
                    itemType = typeof(char);
                }

                //********** RECURSION **********
                //WILD GUESS: Since we are going to the content of an IEnumerable, the namespace of the IEnumerable becomes irrelevant for its content so we give them null instead.
                List <XNode> xnodesForItem = SerializeToXNodes(item, itemType, knownTypes, useXmlSerializerFormat, isRoot: false, isContainedInsideEnumerable: true, parentTypeInformation: typeInformation, nodeDefaultNamespaceIfAny: typeInformation.NamespaceName);

                // Keep only the first node:
                if (xnodesForItem.Count > 1)
                {
                    throw new Exception("When serializing an IEnumerable, we do not expect an item of the enumerable to be serialized as multiple XNodes.");
                }
                XNode nodeForItem = xnodesForItem.First();

                // If it's a value type, add an XElement to surround the node:
                if (nodeForItem is XText)
                {
                    //todo: do we still ever enter this block? In fact, we now add the surrounding XElement in other places.

                    //------------
                    // Value type
                    //------------

                    //we assume namespace of the element is "http://schemas.microsoft.com/2003/10/Serialization/Arrays" as that is what it is for both an array and a list of string
                    //the name of the element should be found in the Dictionary Type --> XName with the item's type
                    //Note: We shoud not arrive here if we cannot find the name in the Dictionary mentioned (except maybe for structs but we'll see when we'll deal with them).
                    XName    elementName = XNamespace.Get("http://schemas.microsoft.com/2003/10/Serialization/Arrays").GetName(DataContractSerializer_ValueTypesHandler.TypesToNames[item.GetType()]); //in this line, we create a XName with the namespace that seems to be used for all Enumerables and a name associated with the type.
                    XElement element     = new XElement(elementName);
                    //  name of the element: use the Dictionary Type --> XName with the item's type
                    element.Add(nodeForItem);
                    nodeForItem = element;
                }

                // Add the node to the resulting collection of nodes:
                result.Add(nodeForItem);
            }

            // If the value is the root, add an XElement "ArrayOf..." to surround the nodes:
            if (isRoot)
            {
                Type itemsType;
                if (DataContractSerializer_Helpers.IsAssignableToGenericEnumerableOrArray(objectType, out itemsType))
                {
                    string elementName = "Array";

                    if (DataContractSerializer_ValueTypesHandler.TypesToNames.ContainsKey(itemsType))
                    {
                        elementName = "ArrayOf" + DataContractSerializer_ValueTypesHandler.TypesToNames[itemsType];
                    }
                    else
                    {
                        // In case of nested types, replace the '+' with '.', and do other changes to obtain the type name to use in the serialization:
                        string itemsTypeName = DataContractSerializer_Helpers.GetTypeNameSafeForSerialization(itemsType);

                        elementName = "ArrayOf" + itemsTypeName;
                    }
                    XElement xElement = new XElement(XNamespace.Get("http://schemas.microsoft.com/2003/10/Serialization/Arrays").GetName(elementName), result);
                    xElement.Add(new XAttribute(XNamespace.Get(DataContractSerializer_Helpers.XMLNS_NAMESPACE).GetName("xmlns:i"), DataContractSerializer_Helpers.XMLSCHEMA_NAMESPACE));
                    return(new List <XNode>()
                    {
                        xElement
                    });
                }
                else
                {
                    throw new SerializationException(string.Format("The type '{0}' cannot be serialized because it does implement IEnumerable<T> nor is it an Array.", objectType.ToString())); //todo: see if we can avoid this limitation.
                }
            }

            return(result);
        }
        static object DeserializeToCSharpObject_Object_WithRecursion(IEnumerable <XNode> content, Type resultType, XElement parentElement, IReadOnlyList <Type> knownTypes, bool ignoreErrors, bool useXmlSerializerFormat)
        {
            // Quit if attempting to deserialize to an interface: //todo: investigate why this may happen.
            if (!resultType.IsInterface)
            {
                string resultTypeFullName = resultType.FullName; // For debugging only, can be removed.

                // Create the resulting class:
                object resultInstance = Activator.CreateInstance(resultType); //todo: replace with "System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type)" so that the type does not require a parameterless constructor.

                // Call the "OnDeserializing" method if any:
                CallOnDeserializingMethod(resultInstance, resultType);

                // Get the type information (namespace, etc.) by reading the DataContractAttribute and similar attributes, if present:
                TypeInformation typeInformation = DataContractSerializer_Helpers.GetTypeInformationByReadingAttributes(resultType, null);

                // Read the members of the target type:
                IEnumerable <MemberInformation> membersInformation = DataContractSerializer_Helpers.GetDataContractMembers(resultType, typeInformation.serializationType, useXmlSerializerFormat);

                // Make a dictionary of the members of the target type for faster lookup:
                Dictionary <string, MemberInformation> memberNameToMemberInformation = new Dictionary <string, MemberInformation>();
                foreach (var memberInformation in membersInformation)
                {
                    string memberName = memberInformation.Name;
                    if (resultType.FullName.StartsWith("System.Collections.Generic.KeyValuePair"))
                    {
                        if (memberName == "key")
                        {
                            memberName = "Key";
                        }
                        else if (memberName == "value")
                        {
                            memberName = "Value";
                        }
                    }
                    if (!memberNameToMemberInformation.ContainsKey(memberName))
                    {
                        memberNameToMemberInformation.Add(memberName, memberInformation);
                    }
                    else
                    {
                        MemberInformation collidingMemberInformation = memberNameToMemberInformation[memberName];
                        throw new InvalidDataContractException(
                                  string.Format(
                                      "Type '{0}' contains two members '{1}' 'and '{2}' with the same data member name '{3}'. Multiple members with the same name in one type are not supported. Consider changing one of the member names using DataMemberAttribute attribute.",
                                      resultType.ToString(),
                                      memberInformation.MemberInfo.Name,
                                      collidingMemberInformation.MemberInfo.Name,
                                      memberName
                                      ));
                    }
                }

                // Populate the values of the properties/members of the class:
                HashSet2 <string> membersForWhichWeSuccessfullSetTheValue = new HashSet2 <string>();
                foreach (XNode node in content)
                {
                    if (node is XElement) // Normally an object property was serialized as an XElement.
                    {
                        XElement xElement    = (XElement)node;
                        XName    elementName = xElement.Name;
                        string   elementNameWithoutNamespace = elementName.LocalName;

                        // Find the member that has the name of the XNode:
                        MemberInformation memberInformation;
                        if (memberNameToMemberInformation.TryGetValue(elementNameWithoutNamespace, out memberInformation))
                        {
                            // Avoid processing nodes that have the same name as other nodes already processed (this can happen in case of [XmlElement] attribute on enumerable members - cf. "special case" below - but it is handled differently):
                            if (!membersForWhichWeSuccessfullSetTheValue.Contains(memberInformation.Name))
                            {
                                object memberValue      = null;
                                Type   memberActualType = memberInformation.MemberType; // Note: this is the initial value. It may be modified below.
                                if (DataContractSerializer_Helpers.IsElementNil(xElement))
                                {
                                    //----------------------
                                    // XNode is "Nil", so we return the default value of the result type
                                    //----------------------

                                    memberValue = DataContractSerializer_Helpers.GetDefault(memberInformation.MemberType);
                                }
                                else
                                {
                                    bool isNull = false;

                                    //foreach (XAttribute attribute in xElement.Attributes(XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance").GetName("nil"))) //doesn't work...
                                    //todo: try removing this foreach since it should be handled in the "if(IsElementDefaut(xElement))" above.
                                    foreach (XAttribute attribute in xElement.Attributes("nil")) //We have to do this here because those usually do not have nodes, which causes problems when doing the recursion.
                                    {
                                        isNull = Convert.ToBoolean(attribute.Value);
                                        if (isNull)
                                        {
                                            memberValue = null;
                                        }
                                    }

                                    if (!isNull)
                                    {
                                        memberActualType = DataContractSerializer_KnownTypes.GetCSharpTypeForNode(xElement, memberInformation.MemberInfo.DeclaringType, memberActualType, knownTypes, memberInformation);

                                        //if the type is nullable, we get the undelying type:
                                        Type nonNullableMemberType = memberActualType;
                                        if (memberActualType.FullName.StartsWith("System.Nullable`1"))
                                        {
                                            nonNullableMemberType = Nullable.GetUnderlyingType(memberActualType);
                                        }

                                        // Recursively create the value for the property:
                                        IEnumerable <XNode> propertyChildNodes = xElement.Nodes();

                                        //********** RECURSION **********
                                        memberValue = DeserializeToCSharpObject(propertyChildNodes, nonNullableMemberType, xElement, knownTypes, ignoreErrors, useXmlSerializerFormat);
                                    }

                                    //---------------------------------
                                    // Handle the special case where there is an [XmlElement] attribute on an enumerable member (XmlSerializer compatibility mode only):
                                    //
                                    // Example:
                                    //      <MyObject>
                                    //         <MyEnumerablePropertyName/>
                                    //         <MyEnumerablePropertyName/>
                                    //         <MyEnumerablePropertyName/>
                                    //      </MyObject>
                                    //
                                    // obtained via:
                                    //      class MyObject
                                    //      {
                                    //          [XmlElement]
                                    //          List<MyType> MyEnumerablePropertyName { get; set; }
                                    //      }
                                    //
                                    // cf. https://docs.microsoft.com/en-us/dotnet/standard/serialization/controlling-xml-serialization-using-attributes
                                    //---------------------------------
                                    Type itemsType = null;
                                    bool specialCaseWhereAnEnumerableHasTheXmlElementAttribute =
                                        (useXmlSerializerFormat &&
                                         memberInformation.HasXmlElementAttribute &&
                                         DataContractSerializer_Helpers.IsAssignableToGenericEnumerableOrArray(memberActualType, out itemsType));
                                    if (specialCaseWhereAnEnumerableHasTheXmlElementAttribute)
                                    {
                                        object deserializedEnumerable = DeserializeToCSharpObject_Enumerable_WithRecursion_SpecialCase(
                                            memberInformation.Name,
                                            content, memberActualType, knownTypes, ignoreErrors, itemsType, useXmlSerializerFormat);
                                        memberValue = deserializedEnumerable;
                                    }

                                    //---------------------------------
                                    // Set the value of the member:
                                    //---------------------------------

                                    DataContractSerializer_Helpers.SetMemberValue(resultInstance, memberInformation, memberValue);
                                    membersForWhichWeSuccessfullSetTheValue.Add(memberInformation.Name);
                                }
                            }
                        }
                        else
                        {
                            //-----------
                            // We ignore missing members, to mimic the behavior of the .NET DataContractSerializer.
                            //-----------
                            //throw new Exception("Member '" + memberName + "' not found in type '" + resultType.Name + "'.");
                        }
                    }
                }

                // In case of XmlSerializer compatibility mode, and [XmlAttribute] attribute on a class member, we also need to deserialize the XAttributes (cf. https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributeattribute(v=vs.110).aspx ):
                if (useXmlSerializerFormat)
                {
                    foreach (XAttribute attribute in parentElement.Attributes())
                    {
                        XName attributeName = attribute.Name;
                        // We assume that the object properties have no namespace //todo: fix this assumption, cf. "XmlAttributeAttribute.Namespace" for example (note: repetition of "Attribute" is intended)
                        if (string.IsNullOrEmpty(attributeName.NamespaceName))
                        {
                            string attributeNameWithoutNamespace = attributeName.LocalName;

                            // Find the member that has the name of the XAttribute:
                            MemberInformation memberInformation;
                            if (memberNameToMemberInformation.TryGetValue(attributeNameWithoutNamespace, out memberInformation) &&
                                memberInformation.HasXmlAttributeAttribute)
                            {
                                // Avoid processing members that have already been processed (just in case):
                                if (!membersForWhichWeSuccessfullSetTheValue.Contains(memberInformation.Name))
                                {
                                    string attributeValue = attribute.Value;

                                    // Check to see if the expected type is a value type:
                                    if (DataContractSerializer_ValueTypesHandler.TypesToNames.ContainsKey(memberInformation.MemberType))
                                    {
                                        // Attempt to deserialize the string:
                                        object memberValue = DataContractSerializer_ValueTypesHandler.ConvertStringToValueType(attributeValue, memberInformation.MemberType);

                                        // Set the value of the member:
                                        DataContractSerializer_Helpers.SetMemberValue(resultInstance, memberInformation, memberValue);
                                        membersForWhichWeSuccessfullSetTheValue.Add(memberInformation.Name);
                                    }
                                    else
                                    {
                                        //todo: report the error?
                                        if (memberInformation.MemberType == typeof(List <int>))
                                        {
                                            string[] splittedElements = attributeValue.Split(' ');

#if !BRIDGE
                                            List <int> listint = splittedElements.Select(Int32.Parse).ToList();
#else
                                            List <int> listint = new List <int>();

                                            foreach (string str in splittedElements)
                                            {
                                                listint.Add(Int32.Parse(str));
                                            }
#endif


                                            DataContractSerializer_Helpers.SetMemberValue(resultInstance, memberInformation, listint);
                                            membersForWhichWeSuccessfullSetTheValue.Add(memberInformation.Name);
                                        }
                                    }
                                }
                                else
                                {
                                    //todo: report the error?
                                }
                            }
                            else
                            {
                                //todo: report the error?
                            }
                        }
                    }
                }

                // Verify that the values of all the members marked as "IsRequired" have been set:
                foreach (var memberInformation in membersInformation)
                {
                    if (memberInformation.IsRequired &&
                        !membersForWhichWeSuccessfullSetTheValue.Contains(memberInformation.Name))
                    {
                        throw new SerializationException(string.Format("The member '{0}' is required but it was not found in the document being deserialized.", memberInformation.Name));
                    }
                }

                // Call the "OnDeserialized" method if any:
                CallOnDeserializedMethod(resultInstance, resultType);

                return(resultInstance);
            }
            else
            {
                return(null);
            }
        }