private DeserializeBase ( System.Xml.Linq.XElement baseElement ) : object | ||
baseElement | System.Xml.Linq.XElement | The element to be deserialized. |
Результат | object |
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;
}
/// <summary> /// Retreives the value of the element from the specified XML element or attribute. /// </summary> /// <param name="o">The object to store the retrieved value at.</param> /// <param name="member">The member of the specified object whose value we intent to retreive.</param> /// <param name="elemValue">The value of the element stored as string.</param> /// <param name="xelemValue">The XML element value to be retreived. If the value to be retreived /// has been stored in an XML attribute, this reference is <c>null</c>.</param> private void RetreiveElementValue(object o, MemberWrapper member, string elemValue, XElement xelemValue) { Type memberType = member.MemberType; // try to retrieve the real-type if specified if (xelemValue != null) { XAttribute realTypeAttribute = xelemValue.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName); if (realTypeAttribute != null) { Type realType = ReflectionUtils.GetTypeByName(realTypeAttribute.Value); if (realType != null) { memberType = realType; } } } if (xelemValue != null && XMLUtils.IsElementCompletelyEmpty(xelemValue) && !ReflectionUtils.IsBasicType(memberType) && !member.IsTreatedAsCollection && !member.IsTreatedAsDictionary && !AtLeastOneOfMembersExists(xelemValue, memberType)) { try { member.SetValue(o, member.DefaultValue); } catch { OnExceptionOccurred(new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue), member.TreatErrorsAs); } } else if (memberType == typeof(string)) { if (String.IsNullOrEmpty(elemValue) && xelemValue != null) { if (xelemValue.IsEmpty) elemValue = null; else elemValue = String.Empty; } try { member.SetValue(o, elemValue); } catch { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), this.m_defaultExceptionType); } } else if (ReflectionUtils.IsBasicType(memberType)) { object convertedObj; if (ReflectionUtils.IsNullable(memberType) && String.IsNullOrEmpty(elemValue)) { convertedObj = member.DefaultValue; } else { convertedObj = ReflectionUtils.ConvertBasicType(elemValue, memberType); } try { try { member.SetValue(o, convertedObj); } catch { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), m_defaultExceptionType); } } catch (Exception ex) { if (ex is YAXException) { throw; } this.OnExceptionOccurred(new YAXBadlyFormedInput(member.Alias.LocalName, elemValue), member.TreatErrorsAs); try { member.SetValue(o, member.DefaultValue); } catch { this.OnExceptionOccurred(new YAXDefaultValueCannotBeAssigned(member.Alias.LocalName, member.DefaultValue), m_defaultExceptionType); } } } else if (member.IsTreatedAsDictionary && member.DictionaryAttributeInstance != null) { DeserializeTaggedDictionaryMember(o, member, xelemValue); } else if (member.IsTreatedAsCollection) { DeserializeCollectionMember(o, member, memberType, elemValue, xelemValue); } else { var ser = new YAXSerializer(memberType, m_exceptionPolicy, m_defaultExceptionType, m_serializationOption); ser.SetNamespaceToOverrideEmptyNamespace( member.Namespace. IfEmptyThen(this.TypeNamespace). IfEmptyThenNone()); ser.IsCraetedToDeserializeANonCollectionMember = !(member.IsTreatedAsDictionary || member.IsTreatedAsCollection); if (m_desObject != null) // i.e. it is in resuming mode { ser.SetDeserializationBaseObject(member.GetValue(o)); } object convertedObj = ser.DeserializeBase(xelemValue); m_parsingErrors.AddRange(ser.ParsingErrors); try { member.SetValue(o, convertedObj); } catch { this.OnExceptionOccurred(new YAXPropertyCannotBeAssignedTo(member.Alias.LocalName), this.m_defaultExceptionType); } } }