private static void ScanArrayRanks(IDataAdapter data, Type elementType, int[] lengths, int index) { if (index == lengths.Length - 1 && elementType.IsPrimitive) { string value = data.GetStringValue(); lengths[index] = ByteUtils.GetBytesInBase64(value) / ByteUtils.GetSizeOf(elementType); return; } int count = 0; IDataAdapter firstChild = null; foreach (IDataAdapter e in data.GetArray().GetChildren()) { if (firstChild == null) { firstChild = e; } count++; } lengths[index] = count; if (index < lengths.Length - 1) { ScanArrayRanks(firstChild, elementType, lengths, index + 1); } }
private void DeserializeContainer(ref object container, Type type, Type elementType, IDataAdapter data, string addMethodName, bool reverse = false) { if (container == null) { container = TypeCache.CreateParameterless(type); } Action <object, object> addAction = null; if (!TypeCache.TryGetTypeAccessor(type, ref addAction)) { addAction = InvocationHelper.CreateSetDelegate(type, elementType, addMethodName); TypeCache.AddTypeAccessor(type, addAction); } if (elementType.IsPrimitive) { byte[] buffer = Convert.FromBase64String(data.GetStringValue()); int size = ByteUtils.GetSizeOf(elementType); int count = buffer.Length / size; Func <byte[], int, object> reader = ByteUtils.GetBinaryReader(elementType); if (reverse) { for (int i = count - 1; i >= 0; i--) { addAction(container, reader(buffer, size * i)); } } else { for (int i = 0; i < count; i++) { addAction(container, reader(buffer, size * i)); } } return; } IDataArray array = data.GetArray(); if (reverse) { foreach (IDataAdapter element in array.GetChildrenReversed()) { addAction(container, DeserializeObject(elementType, element, null)); } } else { foreach (IDataAdapter element in array.GetChildren()) { addAction(container, DeserializeObject(elementType, element, null)); } } }
private void DeserializeArrayRank(Array array, Type elementType, int[] coords, int r, IDataAdapter data) { if (r == coords.Length - 1) { if (elementType.IsPrimitive) { byte[] buffer = Convert.FromBase64String(data.GetStringValue()); int size = ByteUtils.GetSizeOf(elementType); int count = array.GetLength(r); Func <byte[], int, object> reader = ByteUtils.GetBinaryReader(elementType); for (int i = 0; i < count; i++) { coords[r] = i; array.SetValue(reader(buffer, i * size), coords); } } else { int index = 0; foreach (IDataAdapter element in data.GetArray().GetChildren()) { coords[r] = index++; array.SetValue(DeserializeObject(elementType, element, null), coords); } } } else { int index = 0; foreach (IDataAdapter element in data.GetArray().GetChildren()) { coords[r] = index++; DeserializeArrayRank(array, elementType, coords, r + 1, element); } } }
private void DeserializeContainer(ref object container, Type type, Type elementType, Type returnType, IDataAdapter data, string addMethodName) { if (container == null) { container = TypeCache.CreateParameterless(type); } Func <object, object, object> addFunc = null; if (!TypeCache.TryGetTypeAccessor(type, ref addFunc)) { addFunc = InvocationHelper.CreateGetSetDelegate(type, elementType, returnType, addMethodName); TypeCache.AddTypeAccessor(type, addFunc); } foreach (IDataAdapter element in data.GetArray().GetChildren()) { addFunc(container, DeserializeObject(elementType, element, null)); } }
/// <summary> /// Deserialize object from source data. /// </summary> /// <typeparam name="T">Type of the class to deserialize root. Use <see cref="object"/> if class is unknown.</typeparam> /// <param name="data">Data source to deserialize from</param> /// <returns>The object or root of object model deserialized from <paramref name="data"/>.</returns> /// <exception cref="SerializationException">thrown when deserialization fails</exception> public T DeserializeObject <T>(IDataAdapter data) { maxObjId = 1; objectCache.Clear(); flags = (OptimizationFlags)data.GetIntValue(ATTRIBUTE_FLAGS, true); IDataAdapter types = data.GetChild(ELEMENT_TYPES); if (types != null) { IDataArray array = types.GetArray(); int index = 1; foreach (IDataAdapter child in array.GetChildren()) { typeCache.Add(index++, InternalResolveTypes(child.GetStringValue())); } } return((T)DeserializeObject(typeof(T), data, null)); }
private void DeserializeContainer(Type type, TypeCategory category, IDataAdapter data, ref object target) { // arrays if (category == TypeCategory.Array) { Type elementType = type.GetElementType(); int rank = (int)data.GetIntValue(ATTRIBUTE_ARRAY_RANK, true); if (rank == 0) { rank = 1; } int[] lengths = new int[rank]; ScanArrayRanks(data, elementType, lengths, 0); Array array; if (target == null) { target = array = Array.CreateInstance(elementType, lengths); } else { array = (Array)target; } int[] coords = new int[array.Rank]; DeserializeArrayRank(array, elementType, coords, 0, data); return; } // non generic containers switch (category) { case TypeCategory.IList: DeserializeContainer(ref target, type, typeof(object), data, "Add"); return; case TypeCategory.Queue: DeserializeContainer(ref target, type, typeof(object), data, "Enqueue"); return; case TypeCategory.Stack: DeserializeContainer(ref target, type, typeof(object), data, "Push", true); return; } // generics Type[] genericArgs = TypeCache.GetTypeGenericArgs(type); switch (category) { case TypeCategory.GenericIList: DeserializeContainer(ref target, type, genericArgs[0], data, "Add"); return; case TypeCategory.GenericQueue: DeserializeContainer(ref target, type, genericArgs[0], data, "Enqueue"); return; case TypeCategory.GenericStack: DeserializeContainer(ref target, type, genericArgs[0], data, "Push", true); return; case TypeCategory.ISet: DeserializeContainer(ref target, type, genericArgs[0], typeof(bool), data, "Add"); return; case TypeCategory.LinkedList: DeserializeContainer(ref target, type, genericArgs[0], typeof(LinkedListNode <>).MakeGenericType(genericArgs[0]), data, "AddLast"); return; } if (category == TypeCategory.IDictionary) { if (target == null) { target = TypeCache.CreateParameterless(type); } Action <object, object, object> setAction = null; if (!TypeCache.TryGetTypeAccessor(type, ref setAction)) { setAction = InvocationHelper.CreateSetDelegate(type, genericArgs[0], genericArgs[1], "Add"); TypeCache.AddTypeAccessor(type, setAction); } foreach (IDataAdapter element in data.GetArray().GetChildren()) { setAction( target, DeserializeObject(genericArgs[0], element.GetChild("Key"), null), DeserializeObject(genericArgs[1], element.GetChild("Value"), null) ); } } }