예제 #1
0
        /// <summary>
        /// Check an XmlElement to see if it includes a specific "Type" attribute. If so, return
        /// the actual Type associated with that attribute's value.
        /// </summary>
        /// <param name="_xml">The XmlElement containing the field's information</param>
        /// <param name="_defaultType">
        /// If there is no Type attribute, then return this value as the "default"
        /// </param>
        /// <returns>
        /// NULL if no Type attribute was found, or the Type object corresponding the value of
        /// the Type attribute
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown if there is a Type attribute, but that attribute's value cannot be turned
        /// into a Type object.
        /// </exception>
        private Type GetTypeFromXmlOrDefault(XmlElement _xml, Type _defaultType)
        {
            var sType = XmlExtensions.GetAttributeValue(_xml, m_context.TypeAttributeName);

            if (sType == null) // There is no explicit Type specifier (XmlAttribute)
            {
                return(_defaultType);
            }

            var explicitType = Lib.BetterGetType(sType, true);

            if (explicitType == null)
            {
                // The XML had an explicit Type, but that Type couldn't be found. So... If we
                // are trying to deserialize a Type that uses EntitySemantics, we assume that
                // the destination Type is sufficient to figure out what to deserialize. If the
                // destination Type is wholly inadequate to "receive" the data in the XML, the
                // application is at fault. For Entities, this type of mismatch is OK.
                if (CEntityTypeData.UsesEntitySemantics(_defaultType))
                {
                    return(_defaultType);
                }

                // However, if this isn't using EntitySemantics, then throw an exception as the
                // Type is unknown.
                throw new XDeserializationError("An Attribute was found for an Explicit Type, but it could not be turned into a Type: " + sType);
            }

            return(explicitType);
        }
예제 #2
0
        /// <summary>
        /// The Type uses EntitySemantics. See <see cref="CEntityTypeData"/> for more info on
        /// EntitySemantics
        /// </summary>
        /// <param name="_xml">The XML containing the data</param>
        /// <param name="_type">
        /// The Type that has already been determined to use Entity Semantics
        /// </param>
        /// <param name="_workingObject">Where to put the resulting object</param>
        private void DeserializeUsingEntitySemantics(XmlElement _xml, Type _type, CWorkingObject _workingObject)
        {
            var obj      = _workingObject.GetExistingOrCreateNew(_type);
            var typeData = CEntityTypeData.GetTypeData(_type);

            for (var i = 0; i < typeData.NonCollectionProperties.Length; i++)
            {
                var prop = typeData.NonCollectionProperties[i];
                var xml  = _xml[prop.Name];

                if (xml != null) // There was some XmlElement for the property
                {
                    // This isn't a Field, and we're using EntitySemantics, so use there's
                    // nothing to query
                    PushCurrentField(null);

                    var propVal = FrameworkDeserialize(xml, prop.PropertyType);
                    prop.SetValue(obj, propVal);

                    PopField(); // pop the null we pushed
                }
            }

            for (var i = 0; i < typeData.CollectionProperties.Length; i++)
            {
                var colProp = typeData.CollectionProperties[i];
            }
        }
예제 #3
0
        /// <summary>
        /// Apply any surrogates to the object for serialization
        /// </summary>
        /// <param name="_object">The object that may be serialized with a surrogate</param>
        /// <param name="_elementForObject">
        /// The XmlElement that is to receive the object data
        /// </param>
        /// <param name="_useType">
        /// The Type that the object should be treated as. If NULL, use object.GetType()
        /// </param>
        /// <returns>
        /// TRUE if the serialziation was completed by a surrogate, FALSE if the framework
        /// should do its job.
        /// </returns>
        private bool ApplySurrogates(object _object, XmlElement _elementForObject, Type _useType)
        {
            // If nothing is sent in, then do nothing.
            if (_object == null)
            {
                return(false);
            }

            // Duplicate References are a "special" kind of built-in surrogate- If this object
            // has been serialized before, then simply refer to that version and return true.
            if (HandleDuplicateReferences(_object, _elementForObject))
            {
                return(true);
            }

            // Setup
            var oType      = _useType ?? _object.GetType();
            var isComplete = false;

            // Check if the object is a dynamic proxy created by Entity Framework
            if (CEntityTypeData.UsesEntitySemantics(oType))
            {
                // There are important conventions and differences when dealing with Entities
                SerializeUsingEntitySemantics(_object, oType, _elementForObject);
                return(true);
            }

            // Check the external surrogate
            var externalSurrogate = GetExternalSurrogate(oType);

            if (externalSurrogate != null)
            {
                isComplete = externalSurrogate.Serialize(_object, _useType, _elementForObject, this);
            }
            if (isComplete)
            {
                return(true);
            }

            // Check implicit surrogates
            var typeData     = CTypeData.GetTypeData(oType);
            var impSurrogate = typeData.ImplicitSurrogate;

            if (impSurrogate != null)
            {
                isComplete = impSurrogate.Serialize(_object, _elementForObject, this);
            }

            return(isComplete);
        }
예제 #4
0
        /// <summary>
        /// Check to see if there are surrogates that handle the deserialization.
        /// </summary>
        /// <param name="_xml">The XML containing the object data</param>
        /// <param name="_type">The TYPE that we're trying to deserialize</param>
        /// <param name="_workingObject">
        /// A "Working Object" that deserializers use to determine if they need to create a new
        /// object or if they have an object that they can deserialize into.
        /// </param>
        /// <returns>
        /// TRUE if a surrogate was successful in completing the deserialization of the object,
        /// or FALSE if the surrogates were not able to complete all deserialization
        /// </returns>
        private bool ApplySurrogates(XmlElement _xml, Type _type, CWorkingObject _workingObject)
        {
            var isComplete = false;

            _workingObject.WorkingType = _type;

            // Check for EntitySemantics as a special and overriding Surrogate method The
            // UseEntitySemantics on the XML element is ignored, as the destination Type gets to
            // define how it gets deserialized (the attribute may be little more than a Hint to
            // what happened at serializatiion time) See for more information on EntitySemantics
            if (CEntityTypeData.UsesEntitySemantics(_type))
            {
                DeserializeUsingEntitySemantics(_xml, _type, _workingObject);
                return(true);
            }

            // Check for external surrogates
            var externalSurrogate = GetExternalSurrogate(_type);

            if (externalSurrogate != null)
            {
                isComplete = externalSurrogate.Deserialize(_workingObject, _xml, this);
            }
            if (isComplete)
            {
                return(true);
            }

            // Check the Implicit surrogates if the External surrogate(s) didn't finish the
            // deserialization
            var typeData          = CTypeData.GetTypeData(_type);
            var implicitSurrogate = typeData.ImplicitSurrogate;

            if (implicitSurrogate != null && implicitSurrogate.HasSurrogate)
            {
                isComplete = implicitSurrogate.Deserialize(_workingObject, _xml, this);
            }
            if (isComplete)
            {
                return(true);
            }

            return(false);
        }
예제 #5
0
        /// <summary>
        /// This "different" serializer handles Properties, not Fields, and conforms to the
        /// conventions found in Microsoft's Entity Framework
        /// </summary>
        /// <param name="_object"></param>
        /// <param name="_useType"></param>
        /// <param name="_elementForObject"></param>
        private void SerializeUsingEntitySemantics(object _object, Type _useType, XmlElement _elementForObject)
        {
            XmlExtensions.AddAttribute(_elementForObject, m_context.UseEntitySemanticsAttributeName, "1");

            // Gets (cached) type data pertinent to serializing an Entity
            var typeData = CEntityTypeData.GetTypeData(_useType);

            // First serialize all the "single" properties- No collections
            for (var i = 0; i < typeData.NonCollectionProperties.Length; i++)
            {
                var prop = typeData.NonCollectionProperties[i];

                var val = prop.GetValue(_object);
                FrameworkSerialize(prop.Name, val, _elementForObject, prop.PropertyType);
            }

            // Now serialize all the collections which are presumed to be the "Many" in a
            // Many-To-One relationship. The exact Type of the collection in this object is
            // irrelevant because the collection should merely implement ICollection for the
            // deserialization, and the deserialization target class should determine the exact
            // collection Type, or if its an Interface the PreferredCollectionType on the
            // AUseEntitySemantics attribute will dictate what to create.
            for (var i = 0; i < typeData.CollectionProperties.Length; i++)
            {
                var col = typeData.CollectionProperties[i];
                var collectionElement = XmlExtensions.AddElement(_elementForObject, col.Name);

                Type elementType = null; // set if the PropertyType is a generic collection
                if (col.PropertyType.IsGenericType)
                {
                    elementType = col.PropertyType.GetGenericArguments()[0];
                }

                foreach (var item in col.GetValue(_object) as System.Collections.IEnumerable)
                {
                    FrameworkSerialize(m_context.ArrayElementName, item, collectionElement, elementType);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Create an XmlElement for an object. Do not populate the new element.
        /// </summary>
        /// <remarks>
        /// FieldRenamers are NOT called at this level- the caller of this method needs to
        /// handle all field renaming
        /// </remarks>
        /// <param name="_elementName">
        /// The name that should be assigned to the newly created element
        /// </param>
        /// <param name="_expectedType">
        /// The expected type of the object. Used to decide whether or not to add explicit Type
        /// data
        /// </param>
        /// <param name="_object">The object that is being serialized</param>
        /// <param name="_parentNode">The XML node that the new node will be a child of</param>
        /// <returns>An XmlElement with some basic attributes for an object</returns>
        private XmlElement CreateElementForValue(string _elementName, object _object, XmlNode _parentNode, Type _expectedType)
        {
            var fixedElementName = FixMemberName(_elementName);
            var elem             = XmlExtensions.CreateElement(_parentNode, fixedElementName);

            if (_object == null)
            {
                XmlExtensions.AddAttribute(elem, m_context.NullAttributeName, m_context.NullAttributeValue);
            }
            else
            {
                var oType = _object.GetType();
                oType = CEntityTypeData.StripProxyType(oType);

                if (_expectedType != oType) // There must be a Type attribute added
                {
                    XmlExtensions.AddAttribute(elem, m_context.TypeAttributeName, oType.AssemblyQualifiedName);
                }
            }

            return(elem);
        }