private XElement MakeDictionaryElement(
XElement insertionLocation,
XName elementName,
object elementValue,
YAXDictionaryAttribute dicAttrInst,
YAXCollectionAttribute collectionAttrInst)
{
if (elementValue == null)
{
return new XElement(elementName);
}
Type keyType, valueType;
if (!ReflectionUtils.IsIDictionary(elementValue.GetType(), out keyType, out valueType))
{
throw new ArgumentException("elementValue must be a Dictionary");
}
// serialize other non-collection members
var ser = NewInternalSerializer(elementValue.GetType(), elementName.Namespace, insertionLocation);
XElement elem = ser.SerializeBase(elementValue, elementName);
FinalizeNewSerializer(ser, true);
// now iterate through collection members
var dicInst = elementValue as IEnumerable;
bool isKeyAttrib = false;
bool isValueAttrib = false;
bool isKeyContent = false;
bool isValueContent = false;
string keyFormat = null;
string valueFormat = null;
XName keyAlias = elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Key";
XName valueAlias = elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone() + "Value";
XName eachElementName = null;
if (collectionAttrInst != null && !String.IsNullOrEmpty(collectionAttrInst.EachElementName))
{
eachElementName = StringUtils.RefineSingleElement(collectionAttrInst.EachElementName);
if (eachElementName.Namespace.IsEmpty())
RegisterNamespace(eachElementName.Namespace, null);
eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
}
if (dicAttrInst != null)
{
if (dicAttrInst.EachPairName != null)
{
eachElementName = StringUtils.RefineSingleElement(dicAttrInst.EachPairName);
if (eachElementName.Namespace.IsEmpty())
RegisterNamespace(eachElementName.Namespace, null);
eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
}
if (dicAttrInst.SerializeKeyAs == YAXNodeTypes.Attribute)
{
isKeyAttrib = ReflectionUtils.IsBasicType(keyType);
}
else if (dicAttrInst.SerializeKeyAs == YAXNodeTypes.Content)
{
isKeyContent = ReflectionUtils.IsBasicType(keyType);
}
if (dicAttrInst.SerializeValueAs == YAXNodeTypes.Attribute)
{
isValueAttrib = ReflectionUtils.IsBasicType(valueType);
}
else if (dicAttrInst.SerializeValueAs == YAXNodeTypes.Content)
{
isValueContent = ReflectionUtils.IsBasicType(valueType);
}
keyFormat = dicAttrInst.KeyFormatString;
valueFormat = dicAttrInst.ValueFormatString;
keyAlias = StringUtils.RefineSingleElement(dicAttrInst.KeyName ?? "Key");
if (keyAlias.Namespace.IsEmpty())
RegisterNamespace(keyAlias.Namespace, null);
keyAlias = keyAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
valueAlias = StringUtils.RefineSingleElement(dicAttrInst.ValueName ?? "Value");
if (valueAlias.Namespace.IsEmpty())
RegisterNamespace(valueAlias.Namespace, null);
valueAlias = valueAlias.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
}
foreach (object obj in dicInst)
{
object keyObj = obj.GetType().GetProperty("Key").GetValue(obj, null);
object valueObj = obj.GetType().GetProperty("Value").GetValue(obj, null);
bool areKeyOfSameType = true;
bool areValueOfSameType = true;
if (keyObj != null && !keyObj.GetType().EqualsOrIsNullableOf(keyType))
areKeyOfSameType = false;
if (valueObj != null && !valueObj.GetType().EqualsOrIsNullableOf(valueType))
areValueOfSameType = false;
if (keyFormat != null)
{
keyObj = ReflectionUtils.TryFormatObject(keyObj, keyFormat);
}
if (valueFormat != null)
{
valueObj = ReflectionUtils.TryFormatObject(valueObj, valueFormat);
}
if (eachElementName == null)
{
eachElementName = StringUtils.RefineSingleElement(ReflectionUtils.GetTypeFriendlyName(obj.GetType()));
eachElementName = eachElementName.OverrideNsIfEmpty(elementName.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
}
var elemChild = new XElement(eachElementName, null);
if (isKeyAttrib && areKeyOfSameType)
{
elemChild.AddAttributeNamespaceSafe(keyAlias, keyObj, m_documentDefaultNamespace);
}
else if (isKeyContent && areKeyOfSameType)
{
elemChild.AddXmlContent(keyObj);
}
else
{
XElement addedElem = AddObjectToElement(elemChild, keyAlias, keyObj);
if (!areKeyOfSameType)
{
if (addedElem.Parent == null)
{
// sometimes empty elements are removed because its members are serialized in
// other elements, therefore we need to make sure to re-add the element.
elemChild.Add(addedElem);
}
addedElem.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, keyObj.GetType().FullName, m_documentDefaultNamespace);
RegisterYaxLibNamespace();
}
}
if (isValueAttrib && areValueOfSameType)
{
elemChild.AddAttributeNamespaceSafe(valueAlias, valueObj, m_documentDefaultNamespace);
}
else if (isValueContent && areValueOfSameType)
{
elemChild.AddXmlContent(valueObj);
}
else
{
XElement addedElem = AddObjectToElement(elemChild, valueAlias, valueObj);
if (!areValueOfSameType)
{
if (addedElem.Parent == null)
{
// sometimes empty elements are removed because its members are serialized in
// other elements, therefore we need to make sure to re-add the element.
elemChild.Add(addedElem);
}
addedElem.AddAttributeNamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, valueObj.GetType().FullName, m_documentDefaultNamespace);
RegisterYaxLibNamespace();
}
}
elem.Add(elemChild);
}
return elem;
}