private object DeserializeBase(XElement baseElement)
{
m_isSerializing = false;
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, m_documentDefaultNamespace);
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;
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, m_documentDefaultNamespace) != null)
{
elemValue = elem.Value;
xelemValue = elem;
}
else
{
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
{
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, m_documentDefaultNamespace) != null)
{
elemValue = innerelem.Value;
xelemValue = innerelem;
}
else
{
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)
{
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(RemoveDeserializedXmlNodes)
{
if(xattrValue != null) xattrValue.Remove();
else if(xelemValue != null) 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;
}