private static void EmitWriteFields(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 = SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(fieldType); if (methodInfo == null) { methodInfo = typeof(SerializeWriterHelper <, >).MakeGenericType(new Type[] { fieldType, typeof(W) }).GetMethod("Serialize"); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldfld, fieldInfo); il.EmitCall(OpCodes.Call, methodInfo, null); } } }
private static void GenerateSerializeMethod() { object[] @namespace = new object[] { typeof(SerializeWriterHelper <Type, W>).Namespace, typeof(SerializeWriterHelper <Type, W>).Name, typeof(T).Namespace, typeof(T).Name }; string str = string.Format("{0}.{1}.SerializeCore[{2}.{3}]", @namespace); Type[] typeArray = new Type[] { typeof(W).MakeByRefType(), typeof(T) }; DynamicMethod dynamicMethod = new DynamicMethod(str, null, typeArray, typeof(SerializeWriterHelper <T, W>), true); dynamicMethod.DefineParameter(1, ParameterAttributes.In | ParameterAttributes.Out, "writer"); dynamicMethod.DefineParameter(2, ParameterAttributes.In, "value"); ILGenerator lGenerator = dynamicMethod.GetILGenerator(); Type baseType = typeof(T); if (!baseType.IsSerializable && SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType) == null) { throw new SerializationException(string.Format("Type is not serializable: {0}", baseType.AssemblyQualifiedName)); } Label?nullable = null; if (!baseType.IsValueType && SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType) == null) { MethodInfo method = SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(typeof(bool)); if (method == null) { Type type = typeof(SerializeWriterHelper <,>); Type[] typeArray1 = new Type[] { typeof(bool), typeof(W) }; method = type.MakeGenericType(typeArray1).GetMethod("Serialize"); } lGenerator.Emit(OpCodes.Ldarg_0); lGenerator.Emit(OpCodes.Ldarg_1); lGenerator.Emit(OpCodes.Ldnull); lGenerator.Emit(OpCodes.Ceq); lGenerator.Emit(OpCodes.Ldc_I4_0); lGenerator.Emit(OpCodes.Ceq); lGenerator.EmitCall(OpCodes.Call, method, null); lGenerator.Emit(OpCodes.Ldarg_1); nullable = new Label?(lGenerator.DefineLabel()); lGenerator.Emit(OpCodes.Brfalse, nullable.Value); } Stack <Type> types = new Stack <Type>(); while (true) { if (baseType != null) { MethodInfo methodInfo = SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType); if (methodInfo == null) { if (baseType.IsSerializable) { types.Push(baseType); } baseType = baseType.BaseType; } else { SerializeWriterHelper <T, W> .EmitWritePredefinedType(lGenerator, methodInfo); break; } } else { break; } } while (0 < types.Count) { SerializeWriterHelper <T, W> .EmitWriteFields(lGenerator, types.Pop()); } if (nullable.HasValue) { lGenerator.MarkLabel(nullable.Value); } lGenerator.Emit(OpCodes.Ret); SerializeWriterHelper <T, W> .serializeCore = dynamicMethod.CreateDelegate(typeof(SerializeWriterHelper <T, W> .SerializeDelegate)) as SerializeWriterHelper <T, W> .SerializeDelegate; if (typeof(T).IsSealed || SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(typeof(T)) != null) { SerializeWriterHelper <T, W> .serialize = SerializeWriterHelper <T, W> .serializeCore; return; } SerializeWriterHelper <T, W> .serialize = new SerializeWriterHelper <T, W> .SerializeDelegate(SerializeWriterHelper <T, W> .SerializeCoreVirtual); }