private static void EmitReadFields(ILGenerator il, Type type) { foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral && !fieldInfo.IsNotSerialized) { Type fieldType = fieldInfo.FieldType; MethodInfo methodInfo = SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(fieldType); if (methodInfo == null) { methodInfo = typeof(SerializeReaderHelper <, >).MakeGenericType(new Type[] { fieldType, typeof(R) }).GetMethod("Deserialize"); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (!type.IsValueType) { il.Emit(OpCodes.Ldind_Ref); } il.Emit(OpCodes.Ldflda, fieldInfo); il.EmitCall(OpCodes.Call, methodInfo, null); } } }
private static void GenerateDeserializeMethod() { object[] @namespace = new object[] { typeof(SerializeReaderHelper <T, R>).Namespace, typeof(SerializeReaderHelper <T, R>).Name, typeof(T).Namespace, typeof(T).Name }; string str = string.Format("{0}.{1}.DeserializeCore[{2}.{3}]", @namespace); Type[] typeArray = new Type[] { typeof(R).MakeByRefType(), typeof(T).MakeByRefType() }; DynamicMethod dynamicMethod = new DynamicMethod(str, null, typeArray, typeof(SerializeReaderHelper <T, R>), true); dynamicMethod.DefineParameter(1, ParameterAttributes.In | ParameterAttributes.Out, "reader"); dynamicMethod.DefineParameter(2, ParameterAttributes.Out, "value"); ILGenerator lGenerator = dynamicMethod.GetILGenerator(); Type baseType = typeof(T); if (!baseType.IsSerializable && SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(baseType) == null) { throw new SerializationException(string.Format("Type is not serializable: {0}", baseType.AssemblyQualifiedName)); } Label?nullable = null; if (baseType.IsValueType) { lGenerator.Emit(OpCodes.Ldarg_1); lGenerator.Emit(OpCodes.Initobj, baseType); } else if (SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(baseType) == null) { MethodInfo method = SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(typeof(bool)); if (method == null) { Type type = typeof(SerializeReaderHelper <,>); Type[] typeArray1 = new Type[] { typeof(bool), typeof(R) }; method = type.MakeGenericType(typeArray1).GetMethod("Deserialize"); } lGenerator.Emit(OpCodes.Ldarg_0); LocalBuilder localBuilder = lGenerator.DeclareLocal(typeof(bool)); lGenerator.Emit(OpCodes.Ldloca_S, localBuilder); lGenerator.EmitCall(OpCodes.Call, method, null); lGenerator.Emit(OpCodes.Ldloc, localBuilder); nullable = new Label?(lGenerator.DefineLabel()); lGenerator.Emit(OpCodes.Brfalse, nullable.Value); if (baseType.IsInterface || baseType.IsAbstract) { lGenerator.Emit(OpCodes.Ldstr, string.Format("Type cannot be properly initialized: {0}", baseType.AssemblyQualifiedName)); Type type1 = typeof(SerializationException); Type[] typeArray2 = new Type[] { typeof(string) }; ConstructorInfo constructor = type1.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, typeArray2, null); lGenerator.Emit(OpCodes.Newobj, constructor); lGenerator.Emit(OpCodes.Throw); } else { lGenerator.Emit(OpCodes.Ldarg_1); ConstructorInfo constructorInfo = baseType.GetConstructor(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (constructorInfo == null) { MethodInfo methodInfo = typeof(RuntimeTypeHandle).GetMethod("Allocate", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method1 = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public); lGenerator.Emit(OpCodes.Ldtoken, baseType); lGenerator.Emit(OpCodes.Call, method1); lGenerator.EmitCall(OpCodes.Call, methodInfo, null); } else { lGenerator.Emit(OpCodes.Newobj, constructorInfo); } lGenerator.Emit(OpCodes.Stind_Ref); } } Stack <Type> types = new Stack <Type>(); while (true) { if (baseType != null) { MethodInfo methodInfo1 = SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(baseType); if (methodInfo1 == null) { if (baseType.IsSerializable) { types.Push(baseType); } baseType = baseType.BaseType; } else { SerializeReaderHelper <T, R> .EmitReadPredefinedType(lGenerator, methodInfo1); break; } } else { break; } } while (0 < types.Count) { SerializeReaderHelper <T, R> .EmitReadFields(lGenerator, types.Pop()); } if (nullable.HasValue) { lGenerator.MarkLabel(nullable.Value); } lGenerator.Emit(OpCodes.Ret); SerializeReaderHelper <T, R> .deserializeCore = dynamicMethod.CreateDelegate(typeof(SerializeReaderHelper <T, R> .DeserializeDelegate)) as SerializeReaderHelper <T, R> .DeserializeDelegate; if (typeof(T).IsSealed || SerializeReaderHelper <T, R> .FindDefinedDeserializeMethod(typeof(T)) != null) { SerializeReaderHelper <T, R> .deserialize = SerializeReaderHelper <T, R> .deserializeCore; return; } SerializeReaderHelper <T, R> .deserialize = new SerializeReaderHelper <T, R> .DeserializeDelegate(SerializeReaderHelper <T, R> .DeserializeVirtual); }