private object DeserializeCollectionValue(Type colType, XElement xelemValue, XName memberAlias, YAXCollectionAttribute colAttrInstance)
{
object containerObj = null;
if (ReflectionUtils.IsInstantiableCollection(colType))
{
var namespaceToOverride = memberAlias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone();
var containerSer = NewInternalSerializer(colType, namespaceToOverride, null);
containerSer.IsCraetedToDeserializeANonCollectionMember = true;
containerSer.RemoveDeserializedXmlNodes = true;
containerObj = containerSer.DeserializeBase(xelemValue);
FinalizeNewSerializer(containerSer, false);
}
var lst = new List<object>(); // this will hold the actual data items
Type itemType = ReflectionUtils.GetCollectionItemType(colType);
if (ReflectionUtils.IsBasicType(itemType) && colAttrInstance != null && colAttrInstance.SerializationType == YAXCollectionSerializationTypes.Serially)
{
// What if the collection was serialized serially
char[] seps = colAttrInstance.SeparateBy.ToCharArray();
// can white space characters be added to the separators?
if (colAttrInstance.IsWhiteSpaceSeparator)
{
seps = seps.Union(new [] { ' ', '\t', '\r', '\n' }).ToArray();
}
string elemValue = xelemValue.Value;
string[] items = elemValue.Split(seps, StringSplitOptions.RemoveEmptyEntries);
foreach (string wordItem in items)
{
try
{
lst.Add(ReflectionUtils.ConvertBasicType(wordItem, itemType));
}
catch
{
OnExceptionOccurred(new YAXBadlyFormedInput(memberAlias.ToString(), elemValue), m_defaultExceptionType);
}
}
}
else //if the collection was serialized recursively
{
bool isPrimitive = ReflectionUtils.IsBasicType(itemType);
XName eachElemName = null;
if (colAttrInstance != null && colAttrInstance.EachElementName != null)
{
eachElemName = StringUtils.RefineSingleElement(colAttrInstance.EachElementName);
eachElemName = eachElemName.OverrideNsIfEmpty(memberAlias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone());
}
var elemsToSearch = eachElemName == null ? xelemValue.Elements() : xelemValue.Elements(eachElemName);
foreach (XElement childElem in elemsToSearch)
{
Type curElementType = itemType;
bool curElementIsPrimitive = isPrimitive;
XAttribute realTypeAttribute = childElem.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_trueTypeAttrName, m_documentDefaultNamespace);
if (realTypeAttribute != null)
{
Type theRealType = ReflectionUtils.GetTypeByName(realTypeAttribute.Value);
if (theRealType != null)
{
curElementType = theRealType;
curElementIsPrimitive = ReflectionUtils.IsBasicType(curElementType);
}
}
// TODO: check if curElementType is derived or is the same is itemType, for speed concerns perform this check only when elementName is null
if (eachElemName == null && (curElementType == typeof(object) || !ReflectionUtils.IsTypeEqualOrInheritedFromType(curElementType, itemType)))
continue;
if (curElementIsPrimitive)
{
try
{
lst.Add(ReflectionUtils.ConvertBasicType(childElem.Value, curElementType));
}
catch
{
OnExceptionOccurred(new YAXBadlyFormedInput(childElem.Name.ToString(), childElem.Value), m_defaultExceptionType);
}
}
else
{
var namespaceToOverride = memberAlias.Namespace.IfEmptyThen(TypeNamespace).IfEmptyThenNone();
var ser = NewInternalSerializer(curElementType, namespaceToOverride, null);
lst.Add(ser.DeserializeBase(childElem));
FinalizeNewSerializer(ser, false);
}
}
} // end of else if
// Now what should I do with the filled list: lst
Type dicKeyType, dicValueType;
if (ReflectionUtils.IsArray(colType))
{
XAttribute dimsAttr = xelemValue.Attribute_NamespaceSafe(m_yaxLibNamespaceUri + m_dimsAttrName, m_documentDefaultNamespace);
int[] dims = new int[0];
if (dimsAttr != null)
{
dims = StringUtils.ParseArrayDimsString(dimsAttr.Value);
}
Array arrayInstance = null;
if (dims.Length > 0)
{
var lowerBounds = new int[dims.Length]; // an array of zeros
arrayInstance = Array.CreateInstance(itemType, dims, lowerBounds); // create the array
int count = Math.Min(arrayInstance.Length, lst.Count);
// now fill the array
for (int i = 0; i < count; i++)
{
int[] inds = GetArrayDimentionalIndex(i, dims);
try
{
arrayInstance.SetValue(lst[i], inds);
}
catch
{
OnExceptionOccurred(
new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]),
m_defaultExceptionType);
}
}
}
else
{
arrayInstance = Array.CreateInstance(itemType, lst.Count); // create the array
int count = Math.Min(arrayInstance.Length, lst.Count);
// now fill the array
for (int i = 0; i < count; i++)
{
try
{
arrayInstance.SetValue(lst[i], i);
}
catch
{
OnExceptionOccurred(
new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]),
m_defaultExceptionType);
}
}
}
return arrayInstance;
}
else if (ReflectionUtils.IsIDictionary(colType, out dicKeyType, out dicValueType))
{
//The collection is a Dictionary
object dic = containerObj;
foreach (var lstItem in lst)
{
object key = itemType.GetProperty("Key").GetValue(lstItem, null);
object value = itemType.GetProperty("Value").GetValue(lstItem, null);
try
{
colType.InvokeMember("Add", BindingFlags.InvokeMethod, null, dic, new[] { key, value });
}
catch
{
OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), m_defaultExceptionType);
}
}
return dic;
}
else if (ReflectionUtils.IsNonGenericIDictionary(colType))
{
object col = containerObj;
foreach (var lstItem in lst)
{
object key = lstItem.GetType().GetProperty("Key", BindingFlags.Instance | BindingFlags.Public).GetValue(lstItem, null);
object value = lstItem.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public).GetValue(lstItem, null);
try
{
colType.InvokeMember("Add", BindingFlags.InvokeMethod, null, col, new[] { key, value });
}
catch
{
OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), m_defaultExceptionType);
}
}
return col;
}
else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(BitArray)))
{
var bArray = new bool[lst.Count];
for (int i = 0; i < bArray.Length; i++)
{
try
{
bArray[i] = (bool)lst[i];
}
catch
{
}
}
object col = colType.InvokeMember(string.Empty, System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { bArray });
return col;
}
else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Stack)) ||
ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Stack<>)))
{
//object col = colType.InvokeMember(string.Empty, System.Reflection.BindingFlags.CreateInstance, null, null, new object[0]);
object col = containerObj;
const string additionMethodName = "Push";
for (int i = lst.Count - 1; i >= 0; i--) // the loop must be from end to front
{
try
{
colType.InvokeMember(additionMethodName, BindingFlags.InvokeMethod, null, col, new[] { lst[i] });
}
catch
{
OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lst[i]), m_defaultExceptionType);
}
}
return col;
}
else if (ReflectionUtils.IsIEnumerable(colType))
{
if (containerObj == null)
return lst;
object col = containerObj;
string additionMethodName = "Add";
if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Queue)) ||
ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(Queue<>)))
{
additionMethodName = "Enqueue";
}
else if (ReflectionUtils.IsTypeEqualOrInheritedFromType(colType, typeof(LinkedList<>)))
{
additionMethodName = "AddLast";
}
foreach (var lstItem in lst)
{
try
{
colType.InvokeMember(additionMethodName, BindingFlags.InvokeMethod, null, col, new object[] { lstItem });
}
catch
{
OnExceptionOccurred(new YAXCannotAddObjectToCollection(memberAlias.ToString(), lstItem), this.m_defaultExceptionType);
}
}
return col;
}
return null;
}