/// <summary>
		/// Returns a typed version of the Serializer.Serialize method.
		/// </summary>
		/// <param name="t">The <see cref="Type"/> to serialize or deserialize.</param>
		/// <param name="methodType">
		///	<para>The type of method to get; <see cref="TypeMethodType.Serialize"/>,
		///	<see cref="TypeMethodType.Deserialize"/>, or <see cref="TypeMethodType.Compare"/>.</para>
		/// </param>
		/// <returns>
		///	<para>A typed version of the <see cref="Serializer.Serialize{T}(Stream, T)"/> method.</para>
		/// </returns>
		internal static MethodInfo GetTypeMethod(Type t, TypeMethodType methodType)
		{
			MethodInfo method = null;
			Dictionary<Type, MethodInfo> methodTypeMethods = null;

			Debug.WriteLine(string.Format("Getting type method {0} for {1}", methodType.ToString(), t.FullName));

			typeMethodsLock.Read(() =>
				{
					if (typeMethods.TryGetValue(methodType, out methodTypeMethods))
					{
						methodTypeMethods.TryGetValue(t, out method);
					}
				});

			if (method == null)
			{
				Type[] typeArgs = { t };

				//  For simple types, find the corresponding IPrimitiveReader/IPrimitveWriter method
				//  For complex types, get a typed version of the appropriate Serializer method
				//  For enumerations, find the corresponding method for the base type
				if (t.IsEnum)
				{
					method = GetTypeMethod(Enum.GetUnderlyingType(t), methodType);
				}
				else if (t.IsValueType || (t == typeof(string)))
				{
					switch (methodType)
					{
						case TypeMethodType.Serialize:
							method = typeof(IPrimitiveWriter).GetMethod("Write", typeArgs);
							if ((method == null) && (t.IsPrimitive == false))
							{
								method = GenerateWriteStructMethod(t);
							}
							break;

						case TypeMethodType.Deserialize:
							if (t.Name.StartsWith("Nullable"))
							{
								Type[] targs = t.GetGenericArguments();
								method = typeof(IPrimitiveReader).GetMethod(
												string.Format("ReadNullable{0}", targs[0].Name),
												Type.EmptyTypes
												);
							}
							else
							{
								method = typeof(IPrimitiveReader).GetMethod(
												string.Format("Read{0}", t.Name),
												Type.EmptyTypes
												);
							}

							if ((method == null) && (t.IsPrimitive == false))
							{
								method = GenerateReadStructMethod(t);
							}
							break;

						case TypeMethodType.Compare:
							{
								for (
									 Type currentType = t;
									 (currentType != null) && (method == null);
									 currentType = currentType.BaseType
									 )
								{
									method = t.GetMethod(
													"Equals",
													BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly,
													null,
													new [] { currentType },
													null
													);
								}

								if (method == null)
								{
									Debug.WriteLine(string.Format("WARNING: The type {0} does contain a supported Equals method", t.FullName));
								}
							}
							break;
					}

				}
				else // complex type
				{
					//  Get a generic version of a method that can
					//  perform the requested operation and then make
					//  a type-specific version of it
					method = genericMethods[methodType];
					method = method.MakeGenericMethod(typeArgs);
				}

				if ((method == null) && (methodType != TypeMethodType.Compare))
				{
					string msg = string.Format("Failed to resolve handler method for type {0}", t.FullName);
					Debug.Fail(msg);
					throw new NotImplementedException(msg);
				}

				//  Update the method cache
				typeMethodsLock.Write(() => typeMethods[methodType][t] = method);

			} // if (method not created yet)

			return method;
		}
		/// <summary>
		/// Returns a typed version of the Serializer.Serialize method.
		/// </summary>
		/// <param name="t">The <see cref="Type"/> to serialize or deserialize.</param>
		/// <param name="methodType">
		///	<para>The type of method to get; <see cref="TypeMethodType.Serialize"/>,
		///	<see cref="TypeMethodType.Deserialize"/>, or <see cref="TypeMethodType.Compare"/>.</para>
		/// </param>
		/// <returns>
		///	<para>A typed version of the <see cref="Serializer.Serialize{T}(Stream, T)"/> method.</para>
		/// </returns>
		internal static MethodInfo GetTypeMethod(Type t, TypeMethodType methodType)
		{
			MethodInfo method = null;
			Dictionary<Type, MethodInfo> methodTypeMethods = null;

			Debug.WriteLine(string.Format("Getting type method {0} for {1}", methodType.ToString(), t.FullName));

			typeMethodsLock.Read(() =>
				{
					if (typeMethods.TryGetValue(methodType, out methodTypeMethods))
					{
						methodTypeMethods.TryGetValue(t, out method);
					}
				});

			if (method == null)
			{
				Type[] typeArgs = { t };

				//  For simple types, find the corresponding IPrimitiveReader/IPrimitveWriter method
				//  For complex types, get a typed version of the appropriate Serializer method
				//  For enumerations, find the corresponding method for the base type
				if (t.IsEnum)
				{
					method = GetTypeMethod(Enum.GetUnderlyingType(t), methodType);
				}
				else if (t.IsValueType || (t == typeof(string)))
				{
					switch (methodType)
					{
						case TypeMethodType.Serialize:
							method = typeof(IPrimitiveWriter).GetMethod("Write", typeArgs);
							if ((method == null) && (t.IsPrimitive == false))
							{
								method = GenerateWriteStructMethod(t);
							}
							break;

						case TypeMethodType.Deserialize:
							if (t.Name.StartsWith("Nullable"))
							{
								Type[] targs = t.GetGenericArguments();
								method = typeof(IPrimitiveReader).GetMethod(
												string.Format("ReadNullable{0}", targs[0].Name),
												Type.EmptyTypes
												);
							}
							else
							{
								method = typeof(IPrimitiveReader).GetMethod(
												string.Format("Read{0}", t.Name),
												Type.EmptyTypes
												);
							}

							if ((method == null) && (t.IsPrimitive == false))
							{
								method = GenerateReadStructMethod(t);
							}
							break;

						case TypeMethodType.Compare:
							{
								for (
									 Type currentType = t;
									 (currentType != null) && (method == null);
									 currentType = currentType.BaseType
									 )
								{
									method = t.GetMethod(
													"Equals",
													BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly,
													null,
													new [] { currentType },
													null
													);
								}

								if (method == null)
								{
									Debug.WriteLine(string.Format("WARNING: The type {0} does contain a supported Equals method", t.FullName));
								}
							}
							break;
					}

				}
				else // complex type
				{
					//  Get a generic version of a method that can
					//  perform the requested operation and then make
					//  a type-specific version of it
					method = genericMethods[methodType];
					method = method.MakeGenericMethod(typeArgs);
				}

				if ((method == null) && (methodType != TypeMethodType.Compare))
				{
					string msg = string.Format("Failed to resolve handler method for type {0}", t.FullName);
					Debug.Fail(msg);
					throw new NotImplementedException(msg);
				}

				//  Update the method cache
				typeMethodsLock.Write(() => typeMethods[methodType][t] = method);

			} // if (method not created yet)

			return method;
		}