public bool Serialize(IMemberContext source, XObject target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (target.NodeType != XmlNodeType.Element)
                throw new ArgumentException("Parameter must be an XML element.", "target");

            var elem = (XElement)target;

            IObjectContext sourceObject = source.GetValue();

            if (sourceObject == null || sourceObject.GetObject() == null)
            {
                if (_isNullableStrategy.IsNullable(source, elem, adviceRequester))
                {
                    elem.Add(Constants.XsiNilAttribute);
                    return true;
                }

                return false;
            }

            List<IMapping<IMemberContext, XObject>> mappings = _mapper.MapForSerialization(source, elem, adviceRequester)
                .ToList();
            if (mappings == null)
                throw new ArgumentException("Unable to map source '" + source + "' and target '" + target + "'.");

            SerializeRecursively(elem, mappings, adviceRequester);

            return true;
        }
        public void Deserialize(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                return;

            if (source.NodeType != XmlNodeType.Element)
                throw new ArgumentException("Parameter must be an XML element.", "source");

            if (_log.IsDebugEnabled)
                _log.Debug("Deserializing " + source.ToFriendlyName() + " into " + target + ".");

            var elem = (XElement)source;

            Type targetType = _typeConverter.GetActualType(source, target, adviceRequester);
            if (targetType == null)
                throw new ArgumentException("Unable to get target type for target '" + target + "'.");

            IObjectContext targetObject = _objectContextFactory.CreateForDeserialization(target, targetType, adviceRequester);
            if (targetObject == null)
                throw new ArgumentException("Unable to create target object for target '" + target + "'.");

            target.SetValue(targetObject);

            List<IMapping<XObject, IMemberContext>> mappings = _mapper.MapForDeserialization(elem, target, adviceRequester)
                .ToList();
            if (mappings == null)
                throw new ArgumentException("Unable to map source '" + source + "' and target '" + target + "'.");

            DeserializeRecursively(mappings, adviceRequester);

            target.CommitChanges();
        }
        public IEnumerable<IMapping<XObject, IMemberContext>> MapForDeserialization(XElement source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (target == null)
                throw new ArgumentNullException("target");

            var targetObject = target.GetValue();
            foreach (var member in targetObject.Members.Where(m => !m.Attributes.OfType<XmlIgnoreAttribute>().Any()))
            {
                var sourceType = GetSourceTypeAndPotentialNames(member);

                switch (sourceType.Key)
                {
                    case XmlNodeType.Element:
                        foreach (var mapping in GetMappingsFromElement(sourceType.Value, source, targetObject, member, adviceRequester))
                            yield return mapping;
                        break;
                    case XmlNodeType.Attribute:
                        yield return GetMappingFromAttribute(sourceType.Value, source, member);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }
 public IObjectContext CreateForDeserialization(IMemberContext targetMember, Type targetType, IAdviceRequester adviceRequester)
 {
     return Factories
         .Select(f => f.CreateForDeserialization(targetMember, targetType, adviceRequester))
         .Where(d => d != null)
         .FirstOrDefault();
 }
 public IObjectContext CreateForSerialization(IMemberContext sourceMember, object source, IAdviceRequester adviceRequester)
 {
     return Factories
         .Select(f => f.CreateForSerialization(sourceMember, source, adviceRequester))
         .Where(d => d != null)
         .FirstOrDefault();
 }
        protected virtual IDeserializer Select(XObject source, IMemberContext target, Type type, IAdviceRequester adviceRequester)
        {
            var typeCode = Type.GetTypeCode(type);

            switch (typeCode)
            {
                case TypeCode.Empty:
                case TypeCode.DBNull:
                    return null;
                case TypeCode.Object:
                    if (target.ContractType == typeof(TimeSpan))
                        break;
                    if (target.ContractType == typeof(string))
                        break;
                    if (target.ContractType.IsNullable())
                        break;

                    return null;
            }

            if (source == null)
                return GetDeserializer(type);

            if (source.NodeType == XmlNodeType.Element && !((XElement)source).HasElements)
                return GetDeserializer(type);

            if (source.NodeType == XmlNodeType.Attribute)
                return GetDeserializer(type);

            return null;
        }
        public Type GetActualType(Type type, IAdviceRequester adviceRequester)
        {
            Type result = null;

            if (type != null)
            {
                if (type != typeof(string))
                {
                    if (!typeof(IDictionary).IsAssignableFrom(type) &&
                        (!type.IsGenericType || type.GetGenericArguments().Length != 2 || !typeof(IDictionary<,>).MakeGenericType(type.GetGenericArguments()).IsAssignableFrom(type)))
                    {
                        if (type.IsClass && typeof(IEnumerable).IsAssignableFrom(type))
                            result = type;
                        else
                        {
                            if (type.IsInterface && type.IsAssignableFrom(typeof(List<object>)))
                                result = typeof(List<object>);
                            else
                            {
                                if (type.IsGenericType && type.GetGenericArguments().Length == 1 && type.IsAssignableFrom(typeof(List<>).MakeGenericType(type.GetGenericArguments())))
                                    result = typeof(List<>).MakeGenericType(type.GetGenericArguments());
                            }
                        }
                    }
                }
            }

            if (_log.IsDebugEnabled)
                _log.Debug("Converted '" + type + "' to '" + result + "'.");

            return result;
        }
 public Type GetActualType(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
 {
     return Converters
             .Select(c => c.GetActualType(source, target, adviceRequester))
             .Where(t => t != null)
             .FirstOrDefault();
 }
 public IDeserializer Select(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
 {
     return Selectors
             .Select(s => s.Select(source, target, adviceRequester))
             .Where(d => d != null)
             .FirstOrDefault();
 }
        public ISerializer Select(IMemberContext source, XObject target, IAdviceRequester adviceRequester)
        {
            if (target.NodeType != XmlNodeType.Element)
                return null;

            return _serializer;
        }
        public override IDeserializer Select(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            var contractTypeFromAttr = GetContractTypeFromAttributes(source, target);
            if (contractTypeFromAttr == null)
                return null;

            return Select(source, target, contractTypeFromAttr, adviceRequester);
        }
        public IObjectContext CreateForSerialization(IMemberContext sourceMember, object source, IAdviceRequester adviceRequester)
        {
            if (source == null)
                return null;

            ObjectContextInfo contextInfo = GetContextInfo(source.GetType(), adviceRequester);

            return contextInfo.CreateFor(source);
        }
        public IObjectContext CreateForDeserialization(IMemberContext targetMember, Type targetType, IAdviceRequester adviceRequester)
        {
            ObjectContextInfo contextInfo = GetContextInfo(targetType, adviceRequester);

            object target = _instantiator.Create(targetType, adviceRequester);
            if (target == null)
                throw new ArgumentException("Unable to create instance of '" + targetType + "' for member '" + targetMember + "'.");

            return contextInfo.CreateFor(target);
        }
        public bool Serialize(IMemberContext source, XObject target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            var sourceObject = source.GetValue().GetObject();

            if (target.NodeType != XmlNodeType.Element)
                throw new ArgumentException("Parameter must be an XML element.", "source");

            var elem = (XElement)target;

            var xmlSerializable = (IXmlSerializable)sourceObject;

            var memoryStream = new MemoryStream();

            var xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            xmlWriter.WriteStartElement(elem.Name.LocalName);
            xmlWriter.WriteAttributeString("xmlns", "xsi", null, Constants.XmlSchemaInstanceNamespaceAttribute.Value);
            xmlWriter.WriteAttributeString("xmlns", "xsd", null, Constants.XmlSchemaNamespaceAttribute.Value);
            xmlSerializable.WriteXml(xmlWriter);
            xmlWriter.WriteEndElement();
            xmlWriter.Flush();
            memoryStream.Position = 0;

            var tempTarget = XElement.Load(memoryStream);

            if (tempTarget.HasElements)
                foreach (var element in tempTarget.Elements())
                    elem.Add(element);
            else
                elem.SetValue(tempTarget.Value);

            foreach (var attribute in tempTarget.Attributes())
            {
                if (attribute.Name == Constants.XmlSchemaNamespaceAttribute.Name || attribute.Name == Constants.XmlSchemaInstanceNamespaceAttribute.Name)
                    continue;
                elem.Add(attribute);
            }

            foreach (var childElem in elem.Elements())
            {
                var xmlnsXsiAttr = childElem.Attribute(Constants.XmlSchemaInstanceNamespaceAttribute.Name);
                if (xmlnsXsiAttr != null)
                    xmlnsXsiAttr.Remove();

                var xmlnsXsdAttr = childElem.Attribute(Constants.XmlSchemaNamespaceAttribute.Name);
                if (xmlnsXsdAttr != null)
                    xmlnsXsdAttr.Remove();
            }

            return true;
        }
        public IDeserializer Select(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            Type actualType = _typeConverter.GetActualType(source, target, adviceRequester);
            if (actualType == null)
                return null;

            if (_log.IsDebugEnabled)
                _log.Debug("Selected collection deserialization for source '" + source.ToFriendlyName() + "' and target '" + target + "'.");

            return _deserializer;
        }
            public SerializationObjectContext(Type elementType, IEnumerable value, IEnumerable<object> attributes, IObjectContextFactory objectContextFactory, IAdviceRequester adviceRequester)
            {
                if (elementType == null)
                    throw new ArgumentNullException("elementType");
                if (value == null)
                    throw new ArgumentNullException("value");

                _elementType = elementType;
                _value = value;
                Attributes = (attributes ?? Enumerable.Empty<object>()).ToList();
                _objectContextFactory = objectContextFactory;
                _adviceRequester = adviceRequester;
            }
        public IEnumerable<IMapping<XObject, IMemberContext>> MapForDeserialization(XElement source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            var targetObject = target.GetValue();
            if (targetObject == null)
                throw new ArgumentException("Target should have had it value set to a collection at this point.", "target");

            var elementNames = GetElementNames(target);

            return source.Elements()
                    .Where(e => elementNames.Contains(e.Name, CaseInsensitiveXNameComparer.Instance))
                    .Select(elem => new Mapping<XObject, IMemberContext>(elem, targetObject.Members.Single()))
                    .ToList();
        }
        private void SerializeRecursively(XElement targetElement, IEnumerable<IMapping<IMemberContext, XObject>> mappings, IAdviceRequester adviceRequester)
        {
            foreach (IMapping<IMemberContext, XObject> mapping in mappings)
            {
                ISerializer serializer = _recursiveSelector.Select(mapping.Source, mapping.Target, adviceRequester);
                if (serializer == null)
                    throw new ArgumentException("No serializer could be found for source '" + mapping.Source + "' and target '" + mapping.Target + "'.");

                bool shouldAddToTarget = serializer.Serialize(mapping.Source, mapping.Target, adviceRequester);

                if (mapping.AddTargetToParent && shouldAddToTarget)
                    targetElement.Add(mapping.Target);
            }
        }
        private void DeserializeRecursively(IEnumerable<IMapping<XObject, IMemberContext>> mappings, IAdviceRequester adviceRequester)
        {
            foreach (IMapping<XObject, IMemberContext> mapping in mappings)
            {
                IDeserializer deserializer = _recursiveSelector.Select(mapping.Source, mapping.Target, adviceRequester);

                if (deserializer == null && mapping.Source == null)
                    continue;

                if (deserializer == null)
                    throw new ArgumentException("No deserializer could be found for source '" + mapping.Source + "' and target '" + mapping.Target + "'.");

                deserializer.Deserialize(mapping.Source, mapping.Target, adviceRequester);
            }
        }
        public IEnumerable<IMapping<IMemberContext, XObject>> MapForSerialization(IMemberContext source, XElement target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            var elementType = GetElementType(source.GetActualType());
            if (elementType == null)
                throw new ArgumentException("Collection mapper has been invoked for target that is not a known list type: '" + source.GetActualType() + "'.", "target");

            var sourceObject = source.GetValue();
            if (sourceObject == null)
                return Enumerable.Empty<IMapping<IMemberContext, XObject>>();

            return sourceObject.Members
                    .Select(CreateMapping);
        }
        public IDeserializer Select(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                return null;
            if (source.NodeType != XmlNodeType.Element)
                return null;

            var actualType = _typeConverter.GetActualType(source, target, adviceRequester);
            if (actualType == null)
                return null;

            if (!actualType.IsSubTypeOf<IXmlSerializable>())
                return null;

            return _deserializer;
        }
        public IEnumerable<IMapping<IMemberContext, XObject>> MapForSerialization(IMemberContext source, XElement target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (target == null)
                throw new ArgumentNullException("target");

            var sourceObject = source.GetValue();
            if (sourceObject == null)
                return Enumerable.Empty<IMapping<IMemberContext, XObject>>();

            return sourceObject.Members
                               .Where(m => !m.Attributes.OfType<XmlIgnoreAttribute>().Any())
                               .Select(member => CreateMappingForSerialization(member, target))
                               .ToList();
        }
        public virtual object Create(Type type, IAdviceRequester adviceRequester)
        {
            try
            {
                var instance = Activator.CreateInstance(type);

                if (_log.IsDebugEnabled)
                    _log.Debug("Created instance of '" + type + "': " + instance);

                return instance;
            }
            catch (MissingMethodException ex)
            {
                throw new MissingMethodException("No parameterless constructor defined for type '" + type + "'.", ex);
            }
        }
        private ObjectContextInfo GetContextInfo(Type actualType, IAdviceRequester adviceRequester)
        {
            ObjectContextInfo contextInfo;
            using (_lock.EnterReadScope())
                _mapActualTypeToContextInfo.TryGetValue(actualType, out contextInfo);

            if (contextInfo == null)
            {
                using (_lock.EnterWriteScope())
                {
                    if (!_mapActualTypeToContextInfo.TryGetValue(actualType, out contextInfo))
                        _mapActualTypeToContextInfo[actualType] = contextInfo = CreateContextInfo(actualType, adviceRequester);
                }
            }

            return contextInfo;
        }
        public IObjectContext CreateForSerialization(IMemberContext source, object value, IAdviceRequester adviceRequester)
        {
            if (value == null)
                return null;

            var elementType = GetElementTypeForSerialization(value.GetType());
            if (elementType == null)
                return null;

            var attributes = source != null
                                     ? source.Attributes
                                     : Enumerable.Empty<object>();
            attributes = attributes.Concat(value.GetType().GetCustomAttributes(true));

            if (_log.IsDebugEnabled)
                _log.Debug("Created collection object context for serialization for '" + value.GetType() + "' for member '" + source + "'.");

            return new SerializationObjectContext(elementType, (IEnumerable)value, attributes, _recursionFactory, adviceRequester);
        }
        public Type GetActualType(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            if (source.NodeType != XmlNodeType.Element)
                return null;

            var elem = (XElement) source;

            XAttribute attr = elem.Attribute(_attributeName);
            if (attr == null || string.IsNullOrWhiteSpace(attr.Value))
                return null;

            Type result = Type.GetType(attr.Value);

            LogResult(result, attr);

            return result;
        }
        public IObjectContext CreateForDeserialization(IMemberContext target, Type actualType, IAdviceRequester adviceRequester)
        {
            if (actualType == null)
                return null;

            var elementType = GetElementTypeForDeserialization(actualType);
            if (elementType == null)
                return null;

            var list = CreateInstance(actualType, adviceRequester);

            var attributes = target != null
                                     ? target.Attributes
                                     : Enumerable.Empty<object>();
            attributes = attributes.Concat(actualType.GetCustomAttributes(true));

            if (_log.IsDebugEnabled)
                _log.Debug("Created collection object context for deserialization for '" + actualType + "' for member '" + target + "'.");

            return new DeserializationObjectContext(actualType, elementType, list, attributes);
        }
        public override bool IsNullable(IMemberContext source, XElement target, IAdviceRequester adviceRequester)
        {
            List<XmlElementAttribute> xmlElementAttrs = source.Attributes
                .OfType<XmlElementAttribute>()
                .Where(a => string.IsNullOrWhiteSpace(a.ElementName) || a.ElementName == target.Name)
                .ToList();

            XmlElementAttribute xmlElementAttr = xmlElementAttrs.FirstOrDefault();

            if (xmlElementAttrs.Count > 1)
            {
                xmlElementAttr = xmlElementAttrs
                                     .Where(a => !string.IsNullOrWhiteSpace(a.ElementName))
                                     .FirstOrDefault() ?? xmlElementAttr;
            }

            if (xmlElementAttr == null)
                return base.IsNullable(source, target, adviceRequester);

            return xmlElementAttr.IsNullable;
        }
        public void Deserialize(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
        {
            if (source == null)
                return;

            IObjectContext targetObject;
            switch (source.NodeType)
            {
                case XmlNodeType.Element:
                    targetObject = DeserializeFromElement((XElement)source, _type);
                    break;
                case XmlNodeType.Attribute:
                    targetObject = DeserializeFromAttribute((XAttribute)source, _type);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("source", "Unable to deserialize source of type '" + source.NodeType + "'.");
            }

            target.SetValue(targetObject);

            target.CommitChanges();
        }
 public Type GetActualType(XObject source, IMemberContext target, IAdviceRequester adviceRequester)
 {
     return GetActualType(target.ContractType, adviceRequester);
 }