Click here to Skip to main content
11,410,174 members (60,327 online)
Click here to Skip to main content
Articles » Languages » C# » General » Downloads
Add your own
alternative version

Tagged as

Lazy Alternatives - LazyAndWeak and BackgroundLoader

, 1 Dec 2011 CPOL
This article will present two alternatives to Lazy.
LazyAlternatives.zip
LazyAlternatives
LazyAlternatives.suo
LazyAlternativesSample
Properties
Settings.settings
Pfz
Caching
Collections
DataTypes
DynamicObjects
Internal
Extensions
Factoring
Pfz.csproj.user
Pfz.Phone.csproj.user
Pfz.ruleset
Pfz.Silverlight.csproj.user
Pfz.snk
Pfz.suo
PhoneSpecific
Properties
Remoting
Instructions
Internal
Serializers
Udp
Serialization
BinaryBuiltIn
Threading
Contexts
Disposers
Unsafe
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using Pfz.DynamicObjects.Internal;
using Pfz.Extensions;
using Pfz.Remoting;
using Pfz.Remoting.Internal;

namespace Pfz.Serialization
{
	internal sealed class RemotingSerializer:
		BinarySerializerBase
	{
		#region Private Fields
			private RemotingClient _remotingClient;
			private int _idGenerator;
			private int _assemblyGenerator;
			private int _typeGenerator;
			private Stream _stream;
		#endregion

		#region Constructor
			internal RemotingSerializer(RemotingClient remotingClient)
			{
				_remotingClient = remotingClient;
			}
		#endregion
		
		#region Serialization Methods
			private FormatterConverter _formatterConverter = new FormatterConverter();
			private Dictionary<Assembly, int> _allAssemblies;
			private Dictionary<Type, int> _allTypes;
			private Dictionary<object, int> _allValues;
			private Dictionary<object, _ReferenceOrWrapped> _wrappedValues;
			private Dictionary<object, SerializationInfo> _serializationInfos;
			private Dictionary<object, Type> _itemsToReplace;
			
			/// <summary>
			/// Serializes the given object.
			/// </summary>
			public void Serialize(Stream stream, object graph)
			{
				if (stream == null)
					throw new ArgumentNullException("stream");
				
				if (graph == null)
					throw new ArgumentNullException("graph");
				
				_idGenerator = 0;
				_assemblyGenerator = _defaultAssemblies.Count;
				_typeGenerator = _defaultTypes.Count;
				try
				{
					_allAssemblies = new Dictionary<Assembly, int>();
					int countDefaultAssemblies = _defaultAssemblies.Count;
					int assemblyIndex = -1;
					foreach(Assembly assembly in _defaultAssemblies)
					{
						assemblyIndex ++;
						_allAssemblies.Add(assembly, assemblyIndex);
					}
					
					_allTypes = new Dictionary<Type, int>(64);
					int countDefaultTypes = _defaultTypes.Count;
					int typeIndex = -1;
					foreach(Type type in _defaultTypes)
					{
						typeIndex++;
						_allTypes.Add(type, typeIndex);
					}
					
					_allValues = new Dictionary<object, int>(ReferenceComparer.Instance);
					_wrappedValues = new Dictionary<object, _ReferenceOrWrapped>(ReferenceComparer.Instance);
					_itemsToReplace = new Dictionary<object, Type>(ReferenceComparer.Instance);
					_stream = stream;
					
					_InitializeAllValues(typeof(object), graph);
					
					foreach(var fakeType in _itemsToReplace.Values)
						_AddType(fakeType);

					int countAssemblies = _allAssemblies.Count;
					_stream.WriteCompressedInt32(countAssemblies - countDefaultAssemblies);
					foreach(var assembly in _allAssemblies.Keys.Skip(countDefaultAssemblies))
						_stream.WriteString(assembly.FullName);
					
					int countTypes = _allTypes.Count;
					_stream.WriteCompressedInt32(countTypes - countDefaultTypes);
					foreach(var type in _allTypes.Keys.Skip(countDefaultTypes))
					{
						_stream.WriteCompressedInt32(_allAssemblies[type.Assembly]);
						_stream.WriteString(type.FullName);
					}
					
					_allAssemblies = null;
					
					_stream.WriteCompressedInt32(_allValues.Count);
					foreach(var itemReal in _allValues.Keys)
					{
						object item = itemReal;
						Type type = item.GetType();

						_ReferenceOrWrapped referenceOrWrapped;
						if (_wrappedValues.TryGetValue(item, out referenceOrWrapped))
						{
							item = referenceOrWrapped;
							type = referenceOrWrapped.GetType();
						}
						else
						{
							Type fakeType;
							if (_itemsToReplace.TryGetValue(item, out fakeType))
							{
								type = fakeType;
								item = FormatterServices.GetSafeUninitializedObject(type);
							}
						}

						_stream.WriteCompressedInt32(_allTypes[type]);
						
						Array array = item as Array;
						if (array != null)
						{
							int dimensions = array.Rank;
							_stream.WriteCompressedInt32(dimensions);
							
							for (int i=0; i<dimensions; i++)
							{
								_stream.WriteCompressedInt32(array.GetLength(i));
								_stream.WriteCompressedInt32(array.GetLowerBound(i));
							}
						}
						else
						{
							string str = item as string;
							if (str != null)
								_stream.WriteString(str);
						}
					}
					
					_idGenerator = 0;
					_allValues.Clear();
					_Serialize(typeof(object), graph);
				}
				finally
				{
					_allValues = null;
					_allAssemblies = null;
					_allTypes = null;
					_stream = null;
					_serializationInfos = null;
					_itemsToReplace = null;
				}
			}

			private void _AddType(Type type)
			{
				if (!_allTypes.ContainsKey(type))
				{
					_allTypes.Add(type, _typeGenerator++);
					
					Assembly assembly = type.Assembly;
					if (!_allAssemblies.ContainsKey(assembly))
						_allAssemblies.Add(assembly, _assemblyGenerator++);
				}
			}

			[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
			private void _InitializeAllValues(Type expectedType, object graph)
			{
				if (graph == null || graph == DBNull.Value)
					return;
			
				int id;
				if (_allValues.TryGetValue(graph, out id))
					return;
			
				Type typeGraph = graph as Type;
				if (typeGraph != null)
				{
					Assembly assembly = typeGraph.Assembly;
					int assemblyIndex;
					if (!_allAssemblies.TryGetValue(assembly, out assemblyIndex))
					{
						assemblyIndex = _assemblyGenerator++;
						_allAssemblies.Add(assembly, assemblyIndex);
					}
							
					int typeIndex;
					if (!_allTypes.TryGetValue(typeGraph, out typeIndex))
					{
						typeIndex = _typeGenerator++;
						_allTypes.Add(typeGraph, typeIndex);
					}
					return;
				}

				Type realType = graph.GetType();
				if (!realType.IsSerializable || graph is IRemotable || realType.IsSubclassOf(typeof(Delegate)))
				{
					if (expectedType != typeof(object) && !expectedType.IsInterface)
						throw new RemotingException("Graph of type " + realType.FullName + " can't be serialized, because it is not marked as [Serializable], and can't be send by reference, as the expected type is " + expectedType.FullName + " and only System.Object or interface types are valid expected types for remote objects.");

					_allValues.Add(graph, _idGenerator++);
					_ReferenceOrWrapped wrapped;

					_RemotingProxy proxy = null;
					var proxy1 = graph as BaseImplementedProxy;
					if (proxy1 != null)
						proxy = proxy1._proxyObject as _RemotingProxy;

					if (proxy != null && proxy.RemotingClient == _remotingClient)
						wrapped = proxy.GetBackReference();
					else
					{
						if (!realType.IsSubclassOf(typeof(Delegate)) && expectedType != typeof(object) && !expectedType.IsInterface)
							throw new ArgumentException("graph is not serializable.", "graph");

						wrapped = _remotingClient._objectsUsedByTheOtherSide.GetOrWrap(graph);
					}

					_InnerInitializeAllValues(wrapped, wrapped.GetType());
					_wrappedValues.Add(graph, wrapped);
					return;
				}

				BinarySerializerBase._InvokeOnSerializing(graph, new StreamingContext());
			
				ISerializable serializable = graph as ISerializable;
				if (serializable != null || !expectedType.IsValueType || expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					if (serializable != null || !realType.IsValueType)
						_allValues.Add(graph, _idGenerator++);
				}

				if (serializable != null)
				{
					SerializationInfo info = new SerializationInfo(realType, _formatterConverter);
					serializable.GetObjectData(info, new StreamingContext());
					
					if (_serializationInfos == null)
						_serializationInfos = new Dictionary<object, SerializationInfo>();
						
					_serializationInfos[graph] = info;
					foreach(var item in info)
					{
						object value = item.Value;
						_InitializeAllValues(typeof(object), value);
					}
					
					if (info.FullTypeName != realType.FullName || info.AssemblyName != realType.Assembly.FullName)
					{
						Assembly assembly = _AssemblyLoad(info.AssemblyName);
						Type fakeType = assembly.GetType(info.FullTypeName, true);
						realType = fakeType;
						_itemsToReplace[graph] = fakeType;
					}
				}

				if (serializable != null || !expectedType.IsValueType || expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					_AddType(realType);
				
					if (serializable != null)
						return;
				}
					
				if (realType.Assembly == typeof(int).Assembly)
				{
					switch(realType.Name)
					{
						case "Boolean[]":
						case "Byte[]":
						case "Char[]":
						case "Int64[]":
						case "Int32[]":
						case "Int16[]":
						case "UInt64[]":
						case "UInt32[]":
						case "UInt16[]":
						case "SByte[]":
						case "String":
						case "Int32":
						case "Int64":
						case "Int16":
						case "Byte":
						case "UInt32":
						case "UInt64":
						case "UInt16":
						case "SByte":
						case "Single":
						case "Double":
						case "Char":
						case "Boolean":
							return;
					}
					
					if (expectedType == typeof(bool?) || realType == typeof(bool?[]))
						return;
				}

				if (realType.IsArray)
				{
					Array array = (Array)graph;
					Type elementType = realType.GetElementType();
					if (!elementType.IsPrimitive)
					{
						int length = array.Length;
						foreach(var obj in array)
							_InitializeAllValues(elementType, obj);
					}

					return;
				}
				
				if (realType.IsPrimitive)
					throw new NotImplementedException("Need to support more primitives. Failed for: " + realType.FullName + ".");

				_InnerInitializeAllValues(graph, realType);
			}

			private void _InnerInitializeAllValues(object graph, Type realType)
			{
				var fields = _GetFields(realType);
				var values = FormatterServices.GetObjectData(graph, fields);

				int count = fields.Length;
				for (int i = 0; i < count; i++)
				{
					object fieldValue = values[i];
					if (fieldValue == null)
						continue;

					FieldInfo field = fields[i];
					_InitializeAllValues(field.FieldType, fieldValue);
				}
			}
			[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily"), SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
			private void _Serialize(Type expectedType, object graph)
			{
				if (graph == null)
				{
					_stream.WriteByte(3);
					return;
				}
				if (graph == DBNull.Value)
				{
					_stream.WriteByte(4);
					return;
				}
				
				int id;
				if (_allValues.TryGetValue(graph, out id))
				{
					_stream.WriteCompressedInt32(id + 7);
					return;
				}
			
				Type typeGraph = graph as Type;
				if (typeGraph != null)
				{
					int typeIndex = _allTypes[typeGraph];
					_stream.WriteCompressedInt32(6);
					_stream.WriteCompressedInt32(typeIndex);
					return;
				}

				Type realType = graph.GetType();
				if (!realType.IsSerializable || graph is IRemotable || realType.IsSubclassOf(typeof(Delegate)))
				{
					_allValues.Add(graph, _idGenerator++);
					var wrapped = _wrappedValues[graph];
					_stream.WriteByte(0);
					_InnerSerialize(wrapped, wrapped.GetType());
					return;
				}

				ISerializable serializable = graph as ISerializable;
				if (serializable != null || !expectedType.IsValueType || expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					if (serializable == null && realType.IsValueType)
					{
						_stream.WriteByte(5);
						_stream.WriteCompressedInt32(_allTypes[realType]);
					}
					else
					{
						id = _idGenerator++;
						_allValues.Add(graph, id);
						
						if (!(graph is string))
							_stream.WriteByte(0);
					}
				}

				if (serializable != null)
				{
					var info = _serializationInfos[graph];
					
					_stream.WriteCompressedInt32(info.MemberCount);
					foreach(var item in info)
					{
						_stream.WriteString(item.Name);
						
						object value = item.Value;
						_Serialize(typeof(object), value);
					}
					
					_InvokeOnSerialized(graph, new StreamingContext());
					return;
				}

				if (realType.Assembly == typeof(int).Assembly)
				{
					if (expectedType == typeof(bool?))
					{
						bool value = (bool)graph;
						if (value)
							_stream.WriteByte(1);
						else
							_stream.WriteByte(0);
						
						return;
					}
					
					switch(realType.Name)
					{
						case "Boolean[]":
							_stream.WriteBooleanArray((bool[])graph);
							return;
							
						case "Byte[]":
							byte[] byteArray = (byte[])graph;
							_stream.Write(byteArray);
							return;
						
						case "Char[]":
							_stream.WriteString(new string((char[])graph));
							return;
							
						case "Int64[]":
						case "Int32[]":
						case "Int16[]":
						case "UInt64[]":
						case "UInt32[]":
						case "UInt16[]":
						case "SByte[]":
							Type elementType = realType.GetElementType();
							Array array = (Array)graph;
							int length = Buffer.ByteLength(array);
							byteArray = new byte[length];
							Buffer.BlockCopy(array, 0, byteArray, 0, length);
							_stream.Write(byteArray, 0, length);
							return;
						
						case "String":
							_stream.WriteByte(2); // reference string, generating new id.
							return;
						
						case "Int32":
							_stream.Write(BitConverter.GetBytes((int)graph), 0, 4);
							return;
						
						case "Int64":
							_stream.Write(BitConverter.GetBytes((long)graph), 0, 8);
							return;
						
						case "Int16":
							_stream.Write(BitConverter.GetBytes((short)graph), 0, 2);
							return;
						
						case "Byte":
							_stream.WriteByte((byte)graph);
							return;
						
						case "UInt32":
							_stream.Write(BitConverter.GetBytes((uint)graph), 0, 4);
							return;
						
						case "UInt64":
							_stream.Write(BitConverter.GetBytes((ulong)graph), 0, 8);
							return;
						
						case "UInt16":
							_stream.Write(BitConverter.GetBytes((ushort)graph), 0, 2);
							return;
						
						case "SByte":
							_stream.WriteByte((byte)((sbyte)graph));
							return;
							
						case "Single":
							_stream.Write(BitConverter.GetBytes((float)graph), 0, 4);
							return;
							
						case "Double":
							_stream.Write(BitConverter.GetBytes((double)graph), 0, 8);
							return;
						
						case "Char":
							_stream.Write(BitConverter.GetBytes((char)graph), 0, 2);
							return;
						
						case "Boolean":
							_stream.WriteByte((bool)graph ? (byte)1 : (byte)0);
							return;
					}
					
					if (realType == typeof(bool?[]))
					{
						bool?[] array = (bool?[])graph;
						_stream.WriteNullableBooleanArray(array);
						return;
					}
				}
				
				if (realType.IsArray)
				{
					Array array = (Array)graph as Array;
			
					Type elementType = realType.GetElementType();
					foreach(var obj in array)
						_Serialize(elementType, obj);
					
					return;
				}

				if (realType.IsPrimitive)
					throw new NotImplementedException("Need to support more primitives. Failed for: " + realType.FullName + ".");

				_InnerSerialize(graph, realType);

				_InvokeOnSerialized(graph, new StreamingContext());
			}
			private void _InnerSerialize(object graph, Type realType)
			{
				var fields = _GetFields(realType);
				var values = FormatterServices.GetObjectData(graph, fields);

				int count = fields.Length;
				for (int i = 0; i < count; i++)
				{
					object fieldValue = values[i];
					FieldInfo field = fields[i];
					_Serialize(field.FieldType, fieldValue);
				}
			}
		#endregion
		#region Deserialization Methods
			private byte[] _intBytes;
			private object[] _referencedObjects;
			private List<IDeserializationCallback> _callbacks;
			private Type[] _types;
			internal int _wrapCount;
			
			/// <summary>
			/// Deserializes an object from the given stream.
			/// </summary>
			public object Deserialize(Stream stream)
			{
				if (stream == null)
					throw new ArgumentNullException("stream");
					
				_idGenerator = 0;
				
				if (_intBytes == null)
					_intBytes = new byte[8];
					
				try
				{
					_callbacks = new List<IDeserializationCallback>();
					_stream = stream;
					_wrapCount = 0;
					
					int countDefaultAssemblies = _defaultAssemblies.Count;
					int countAssemblies = _stream.ReadCompressedInt32();
					Assembly[] assemblies = new Assembly[countDefaultAssemblies + countAssemblies];
					_defaultAssemblies.CopyTo(assemblies, 0);
					for(int i=0; i<countAssemblies; i++)
					{
						string assemblyName = _stream.ReadString();
						Assembly assembly = _AssemblyLoad(assemblyName);
						assemblies[countDefaultAssemblies + i] = assembly;
					}
					
					int countDefaultTypes = _defaultTypes.Count;
					int countTypes = _stream.ReadCompressedInt32();
					Type[] types = new Type[countDefaultTypes + countTypes];
					_types = types;
					_defaultTypes.CopyTo(types, 0);
					for(int i=0; i<countTypes; i++)
					{
						int assemblyIndex = _stream.ReadCompressedInt32();
						string typeName = _stream.ReadString();
						
						Assembly assembly = assemblies[assemblyIndex];
						Type type = assembly.GetType(typeName, true);
						types[i + countDefaultTypes] = type;
					}
					
					int count = _stream.ReadCompressedInt32();
					_referencedObjects = new object[count];
					for (int i=0; i<count; i++)
					{
						int typeIndex = _stream.ReadCompressedInt32();
						Type type = types[typeIndex];
						
						object instance;
						if (type.IsArray)
						{
							int countDimensions = _stream.ReadCompressedInt32();
							int[] lengths = new int[countDimensions];
							int[] lowerBounds = new int[countDimensions];
							for (int dimension=0; dimension<countDimensions; dimension++)
							{
								lengths[dimension] = _stream.ReadCompressedInt32();
								lowerBounds[dimension] = _stream.ReadCompressedInt32();
							}
							
							instance = Array.CreateInstance(type.GetElementType(), lengths, lowerBounds);
						}
						else
						if (type == typeof(string))
							instance = _stream.ReadString();
						else
							instance = _FormatterServicesGetSafeUninitializedObject(type, new StreamingContext());
							
						_referencedObjects[i] = instance;
					}
					
					object result = _Deserialize(typeof(object));
					
					int countCallbacks = _callbacks.Count;
					for (int i=countCallbacks-1; i>=0; i--)
					{
						IDeserializationCallback callback = _callbacks[i];
						callback.OnDeserialization(new StreamingContext());
					}
					
					return result;
				}
				finally
				{
					_types = null;
					_stream = null;
					_referencedObjects = null;
					_callbacks = null;
				}
			}

			[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
			[SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
			[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
			private object _Deserialize(Type expectedType)
			{
				if (expectedType == typeof(bool?))
				{
					switch(_stream.ReadByteOrThrow())
					{
						case 0:
							return false;
						
						case 1:
							return true;
						
						case 3:
							return null;
					}

					throw new SerializationException("Invalid byte in stream.");
				}

				Type realType = expectedType;
				bool isValueType = expectedType.IsValueType;
				if (!isValueType || typeof(ISerializable).IsAssignableFrom(expectedType) || expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					int nextCommand = _stream.ReadCompressedInt32();
					switch(nextCommand)
					{
						case 6:
							int typeIndex = _stream.ReadCompressedInt32();
							return _types[typeIndex];

						case 5:
						{
							isValueType = true;
							int typeId = _stream.ReadCompressedInt32();
							realType = _types[typeId];
							break;
						}
							
						case 4:
							return DBNull.Value;
							
						case 3:
							return null;
						
						case 2:
							int objectId = _idGenerator;
							_idGenerator++;
							return _referencedObjects[objectId];
							
						case 0:
							break;
						
						default:
							int id = nextCommand - 7;
							
							return _referencedObjects[id];
					}
				}

				object result = null;
				
				if (expectedType.Assembly == typeof(Nullable<>).Assembly)
					if (expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(Nullable<>))
						expectedType = expectedType.GetGenericArguments()[0];
						
				int actualId = -1;
				if (!isValueType || typeof(ISerializable).IsAssignableFrom(expectedType))
				{
					actualId = _idGenerator++;
					result = _referencedObjects[actualId];
					realType = result.GetType();
				}
				
				if (typeof(ISerializable).IsAssignableFrom(realType) || typeof(IObjectReference).IsAssignableFrom(realType))
				{
					SerializationInfo info = new SerializationInfo(expectedType, _formatterConverter);
					int count = _stream.ReadCompressedInt32();
					for(int i=0; i<count; i++)
					{
						string name = _stream.ReadString();
						object value = _Deserialize(typeof(object));
						
						info.AddValue(name, value);
					}
					
					ConstructorInfo constructorInfo = realType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, _deserializationConstructorTypes, null);
					if (constructorInfo == null)
						throw new SerializationException("Couldn't find Deserialization constructor for type " + realType.FullName + ".");
					
					var parameters = new object[]{info, new StreamingContext()};
					if (result == null)
						result = constructorInfo.Invoke(parameters);
					else
						constructorInfo.Invoke(result, parameters);
						
					IDeserializationCallback callback = result as IDeserializationCallback;
					if (callback != null)
						_callbacks.Add(callback);

					IObjectReference reference = result as IObjectReference;
					if (reference != null)
					{
						result = reference.GetRealObject(new StreamingContext());
						
						if (actualId != -1)
							_referencedObjects[actualId] = result;

						callback = result as IDeserializationCallback;
						if (callback != null)
							_callbacks.Add(callback);
					}
					
					_InvokeOnDeserialized(result, new StreamingContext());
					return result;
				}

				if (realType.Assembly == typeof(int).Assembly)
				{
					switch(realType.Name)
					{
						case "Boolean[]":
							_stream.ReadBooleanArray((bool[])result);
							return result;
							
						case "Byte[]":
							_stream.FullRead((byte[])result);
							return result;
							
						case "Char[]":
							string str = _stream.ReadString();
							str.CopyTo(0, (char[])result, 0, str.Length);
							return result;

						case "Int64[]":
						case "Int32[]":
						case "Int16[]":
						case "UInt64[]":
						case "UInt32[]":
						case "UInt16[]":
						case "SByte[]":
							Type elementType = realType.GetElementType();
							Array array = (Array)result;
							int count = array.Length;
							int byteLength = count * Marshal.SizeOf(elementType);
							byte[] byteArray = new byte[byteLength];
							_stream.FullRead(byteArray);
							Buffer.BlockCopy(byteArray, 0, array, 0, byteLength);
							return result;

						case "String":
							throw new SerializationException("Impossible condition in stream.");
							
						case "Int32":
						{
							_stream.FullRead(_intBytes, 0, 4);
							result = BitConverter.ToInt32(_intBytes, 0);
							return result;
						}
						
						case "Int64":
						{
							_stream.FullRead(_intBytes, 0, 8);
							result = BitConverter.ToInt64(_intBytes, 0);
							return result;
						}
						
						case "Int16":
						{
							_stream.FullRead(_intBytes, 0, 2);
							result = BitConverter.ToInt16(_intBytes, 0);
							return result;
						}
						
						case "UInt32":
						{
							_stream.FullRead(_intBytes, 0, 4);
							result = BitConverter.ToUInt32(_intBytes, 0);
							return result;
						}
						
						case "UInt64":
						{
							_stream.FullRead(_intBytes, 0, 8);
							result = BitConverter.ToUInt64(_intBytes, 0);
							return result;
						}
						
						case "UInt16":
						{
							_stream.FullRead(_intBytes, 0, 2);
							result = BitConverter.ToUInt16(_intBytes, 0);
							return result;
						}

						case "Byte":
							result = _stream.ReadByteOrThrow();
							return result;
						
						case "SByte":
							result = (sbyte)_stream.ReadByteOrThrow();
							return result;
						
						case "Single":
						{
							_stream.FullRead(_intBytes, 0, 4);
							result = BitConverter.ToSingle(_intBytes, 0);
							return result;
						}
						
						case "Double":
						{
							_stream.FullRead(_intBytes, 0, 8);
							result = BitConverter.ToDouble(_intBytes, 0);
							return result;
						}
						
						case "Char":
						{
							_stream.FullRead(_intBytes, 0, 2);
							result = BitConverter.ToChar(_intBytes, 0);
							return result;
						}
						
						case "Boolean":
							result = _stream.ReadByteOrThrow() != 0;
							return result;

						case "Type":
							int typeIndex = _stream.ReadCompressedInt32();
							result = _types[typeIndex];
							return result;
					}

					if (realType == typeof(bool?[]))
					{
						_stream.ReadNullableBooleanArray((bool?[])result);
						return result;
					}
				}

				if (realType.IsArray)
				{
					Type elementType = realType.GetElementType();
					Array array = (Array)result;
					
					int dimensions = array.Rank;
					int[] indices = new int[dimensions];
					for (int i=0; i<dimensions; i++)
						indices[i] = array.GetLowerBound(i);
					
					int lastDimension = dimensions-1;
					indices[lastDimension]--;

					while(true)
					{
						int actualDimension = lastDimension;
						while(true)
						{
							int index = indices[actualDimension] + 1;
							if (index <= array.GetUpperBound(actualDimension))
							{
								indices[actualDimension] = index;
								object item = _Deserialize(elementType);
								array.SetValue(item, indices);
								break;
							}

							if (actualDimension == 0)
								return array;
								
							indices[actualDimension] = array.GetLowerBound(actualDimension);
							actualDimension--;
						}
					}
				}

				if (realType.IsPrimitive)
					throw new NotImplementedException("Must support more primitives.");

				{
					var fields = _GetFields(realType);
					int count = fields.Length;
					object[] array = new object[count];
					for(int i=0; i<count; i++)
					{
						FieldInfo field = fields[i];
						object item = _Deserialize(field.FieldType);
						array[i] = item;
					}
					
					if (result == null)
						result = _FormatterServicesGetSafeUninitializedObject(realType, new StreamingContext());
						
					IDeserializationCallback callback = result as IDeserializationCallback;
					if (callback != null)
						_callbacks.Add(callback);
						
					FormatterServices.PopulateObjectMembers(result, fields, array);
					_InvokeOnDeserialized(result, new StreamingContext());
					
					var referenceOrWrapped = result as _ReferenceOrWrapped;
					if (referenceOrWrapped != null)
					{
						result = referenceOrWrapped.GetResult(_remotingClient, this);

						_referencedObjects[actualId] = result;
					}

					return result;
				}
			}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Paulo Zemek
Engineer Microsoft Corporation
United States United States
I started to program computers when I was 11 years old, as a hobbist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.

At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do they work easier, faster and with less errors.

Now I just started working as a Senior Software Engineer at Microsoft.

Want more info or simply want to contact me?
Take a look at: http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com

Codeproject MVP 2012, 2015
Microsoft MVP 2013-2014

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150414.5 | Last Updated 1 Dec 2011
Article Copyright 2011 by Paulo Zemek
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid