/// <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; }