Created
February 6, 2012 20:42
-
-
Save rpgmaker/1754709 to your computer and use it in GitHub Desktop.
Generate Class and Properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static void WriteSerializerClass(ILGenerator il, | |
MethodInfo getSetGetMethod, | |
Type type, int tag, LocalBuilder msLocal, | |
List<Action<ILGenerator>> actions) { | |
var isDefaultLabel = il.DefineLabel(); | |
var isDict = dictType.IsAssignableFrom(type); | |
var isList = listType.IsAssignableFrom(type); | |
var isClass = !isDict && !isList; | |
var ms2Local = il.DeclareLocal(MemoryStreamType); | |
var bufferLocal = il.DeclareLocal(ByteArrayType); | |
var lengthBufferLocal = il.DeclareLocal(ByteArrayType); | |
il.Emit(OpCodes.Brtrue, isDefaultLabel); | |
il.Emit(OpCodes.Newobj, MemoryStreamCtor); | |
il.Emit(OpCodes.Stloc, ms2Local.LocalIndex); | |
if (isClass) { | |
var actionList = new List<Action<ILGenerator>>(); | |
if (actions != null) actionList.AddRange(actions); | |
if (getSetGetMethod != null) | |
actionList.Add(msIL => | |
msIL.Emit(OpCodes.Callvirt, getSetGetMethod)); | |
WriteSerializerProperties(il, type, ms2Local, actionList); | |
} else { | |
//WriteSerializerDictionary(il, type, getSetGetMethod, ms2Local, | |
// actions); | |
il.Emit(OpCodes.Ldloc, ms2Local.LocalIndex); | |
il.Emit(OpCodes.Ldarg_1); | |
il.Emit(OpCodes.Callvirt, getSetGetMethod); | |
if (isDict) | |
il.Emit(OpCodes.Call, | |
WriteDictionaryToMethod.MakeGenericMethod(type)); | |
else | |
il.Emit(OpCodes.Call, | |
WriteListToMethod.MakeGenericMethod(type)); | |
} | |
il.Emit(OpCodes.Ldloc, ms2Local.LocalIndex); | |
il.Emit(OpCodes.Callvirt, MemoryStreamToArrayMethod); | |
il.Emit(OpCodes.Stloc_S, bufferLocal.LocalIndex); | |
il.Emit(OpCodes.Ldloc, ms2Local.LocalIndex); | |
il.Emit(OpCodes.Callvirt, MemoryStreamDisposeMethod); | |
il.Emit(OpCodes.Ldloc_S, bufferLocal.LocalIndex); | |
il.Emit(OpCodes.Ldlen); | |
il.Emit(OpCodes.Conv_I4); | |
il.Emit(OpCodes.Call, Int32ToBytesMethod); | |
il.Emit(OpCodes.Stloc_S, lengthBufferLocal.LocalIndex); | |
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex); | |
il.Emit(OpCodes.Ldloc_S, lengthBufferLocal.LocalIndex); | |
il.Emit(OpCodes.Ldlen); | |
il.Emit(OpCodes.Conv_I4); | |
il.Emit(OpCodes.Ldc_I4, tag); | |
il.Emit(OpCodes.Call, EncodeLengthMethod); | |
il.Emit(OpCodes.Call, WriteBufferMethod); | |
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex); | |
il.Emit(OpCodes.Ldloc_S, lengthBufferLocal.LocalIndex); | |
il.Emit(OpCodes.Call, WriteBufferMethod); | |
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex); | |
il.Emit(OpCodes.Ldloc_S, bufferLocal.LocalIndex); | |
il.Emit(OpCodes.Call, WriteBufferMethod); | |
il.MarkLabel(isDefaultLabel); | |
} | |
static void WriteSerializerProperties(ILGenerator il, Type type, LocalBuilder msLocal, | |
List<Action<ILGenerator>> actions) { | |
var propInfos = type.GetProperties(PropertyBinding) | |
.Union(type.GetInterfaces() | |
.SelectMany(it => it.GetProperties(PropertyBinding))) | |
.Select((p, i) => new { Tag = i + 1, Property = p }); | |
var hashSet = new HashSet<string>(); | |
foreach (var propInfo in propInfos) { | |
var prop = propInfo.Property; | |
var propType = prop.PropertyType; | |
if (hashSet.Contains(prop.Name)) continue; | |
var getSetGetMethod = prop.GetGetMethod(); | |
il.Emit(OpCodes.Ldarg_1); | |
if (actions != null) | |
actions.ForEach(action => action(il)); | |
il.Emit(OpCodes.Callvirt, getSetGetMethod); | |
il.Emit(OpCodes.Call, IsDefaultMethod.MakeGenericMethod(propType)); | |
if (propType.IsComplexType()) { | |
WriteSerializerClass(il, getSetGetMethod, propType, propInfo.Tag, msLocal, actions); | |
continue; | |
} | |
var isDefaultLabel = il.DefineLabel(); | |
il.Emit(OpCodes.Brtrue_S, isDefaultLabel); | |
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex); | |
il.Emit(OpCodes.Ldarg_1); | |
if (actions != null) | |
actions.ForEach(action => action(il)); | |
il.Emit(OpCodes.Callvirt, getSetGetMethod); | |
il.Emit(OpCodes.Ldc_I4, propInfo.Tag); | |
il.Emit(OpCodes.Call, WriteBytesMethod.MakeGenericMethod(propType)); | |
il.MarkLabel(isDefaultLabel); | |
hashSet.Add(prop.Name); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment