Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » C# » General » Downloads
 
Add your own
alternative version

Tagged as

Go to top

Lazy Alternatives - LazyAndWeak and BackgroundLoader

, 1 Dec 2011
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.Extensions;

namespace Pfz.Serialization
{
	/// <summary>
	/// A binary serializer faster and more compressed than custom .Net 
	/// BinaryFormatter.
	/// It DOES NOT take the many serialization attributes 
	/// and other serialization objects into account.
	/// </summary>
	public sealed class OldBinarySerializer:
		OldBinarySerializerBase,
		IFormatter
	{
		#region Private Fields
			private int _idGenerator;
			private int _assemblyGenerator;
			private int _typeGenerator;
			private Stream _stream;
		#endregion
		
		/// <summary>
		/// Gets or sets the Context used by the ISerializable interface.
		/// </summary>
		public StreamingContext Context { get; set; }
		
		#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, 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);
					_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();

						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;
			
				Type realType = graph.GetType();
				if (!realType.IsSerializable)
					throw new ArgumentException("graph is not serializable.", "graph");
				
				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;
				}

				_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 + ".");	

				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;
				}
				
				Type realType = graph.GetType();
				if (!realType.IsSerializable)
					throw new ArgumentException("graph is not serializable.", "graph");
			
				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;
				}

				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, Context);
					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 + ".");	
					
				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);
				}

				_InvokeOnSerialized(graph, Context);
			}
		#endregion
		#region Deserialization Methods
			private byte[] _intBytes;
			private object[] _referencedObjects;
			private List<IDeserializationCallback> _callbacks;
			private Type[] _types;
			
			/// <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;
					
					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, Context);
							
						_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(Context);
					}
					
					return result;
				}
				finally
				{
					_types = null;
					_stream = null;
					_referencedObjects = null;
					_callbacks = null;
				}
			}

			[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:
							return _types[_stream.ReadCompressedInt32()];

						case 5:
							isValueType = true;
							int typeId = _stream.ReadCompressedInt32();
							realType = _types[typeId];
							break;
							
						case 4:
							return DBNull.Value;
							
						case 3:
							return null;
						
						case 2:
							return _referencedObjects[_idGenerator++];
							
						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, Context};
					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(Context);
						
						if (actualId != -1)
							_referencedObjects[actualId] = result;

						callback = result as IDeserializationCallback;
						if (callback != null)
							_callbacks.Add(callback);
					}
					
					_InvokeOnDeserialized(result, Context);
					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, Context);
						
					IDeserializationCallback callback = result as IDeserializationCallback;
					if (callback != null)
						_callbacks.Add(callback);
						
					FormatterServices.PopulateObjectMembers(result, fields, array);
					_InvokeOnDeserialized(result, Context);
					
					return result;
				}
			}
		#endregion

		#region IFormatter Members - Not used, but here to keep some compatibility.
			SerializationBinder IFormatter.Binder
			{
				get
				{
					return null;
				}
				set
				{
					if (value != null)
						throw new NotSupportedException("BinarySerializer does not support setting a Binder.");
				}
			}
			ISurrogateSelector IFormatter.SurrogateSelector
			{
				get
				{
					return null;
				}
				set
				{
					if (value != null)
						throw new NotSupportedException("BinarySerializer does not support setting a SurrogateSelector.");
				}
			}
		#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
Architect
Canada Canada
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.
 
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
Microsoft MVP 2013

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 1 Dec 2011
Article Copyright 2011 by Paulo Zemek
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid