Skip to content

Instantly share code, notes, and snippets.

@rpgmaker
Created February 7, 2012 03:03
Show Gist options
  • Save rpgmaker/1756874 to your computer and use it in GitHub Desktop.
Save rpgmaker/1756874 to your computer and use it in GitHub Desktop.
IL Emit for Dictionary
static void WriteSerializerDictionary(ILGenerator il, Type type,
MethodInfo getSetGetMethod, LocalBuilder msLocal,
List<Action<ILGenerator>> actions) {
var arguments = type.GetGenericArguments();
var valueType = arguments[0];
var keyType = arguments[1];
var keyValuePairType = genericKeyValuePairType.MakeGenericType(keyType, valueType);
var enumeratorLocal = il.DeclareLocal(
genericEnumeratorType.MakeGenericType(keyValuePairType));
var entryLocal = il.DeclareLocal(keyValuePairType);
var startEnumeratorLabel = il.DefineLabel();
var moveNextLabel = il.DefineLabel();
var endEnumeratorLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_1);
if (actions != null)
actions.ForEach(action => action(il));
il.Emit(OpCodes.Callvirt, getSetGetMethod);
il.Emit(OpCodes.Callvirt,
genericDictType.MakeGenericType(keyType, valueType)
.GetMethod("GetEnumerator"));
il.Emit(OpCodes.Stloc, enumeratorLocal.LocalIndex);
il.BeginExceptionBlock();
il.Emit(OpCodes.Br_S, startEnumeratorLabel);
il.MarkLabel(moveNextLabel);
il.Emit(OpCodes.Ldloca_S, enumeratorLocal.LocalIndex);
il.Emit(OpCodes.Call,
enumeratorLocal.LocalType.GetProperty("Current")
.GetGetMethod());
il.Emit(OpCodes.Stloc, entryLocal.LocalIndex);
if (keyType.IsComplexType()) {
//TODO:
} else {
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex);
il.Emit(OpCodes.Ldloca_S, entryLocal.LocalIndex);
il.Emit(OpCodes.Call,
keyValuePairType.GetProperty("Key").GetGetMethod());
il.Emit(OpCodes.Ldc_I4, 1);
il.Emit(OpCodes.Call, WriteBytesMethod.MakeGenericMethod(keyType));
}
if (valueType.IsComplexType()) {
//TODO:
} else {
il.Emit(OpCodes.Ldloc, msLocal.LocalIndex);
il.Emit(OpCodes.Ldloca_S, entryLocal.LocalIndex);
il.Emit(OpCodes.Call,
keyValuePairType.GetProperty("Value").GetGetMethod());
il.Emit(OpCodes.Ldc_I4, 2);
il.Emit(OpCodes.Call, WriteBytesMethod.MakeGenericMethod(valueType));
}
il.MarkLabel(startEnumeratorLabel);
il.Emit(OpCodes.Ldloca_S, enumeratorLocal.LocalIndex);
il.Emit(OpCodes.Call, enumeratorType.GetMethod("MoveNext", MethodBinding));
il.Emit(OpCodes.Brtrue_S, moveNextLabel);
il.Emit(OpCodes.Leave_S, endEnumeratorLabel);
il.BeginFinallyBlock();
il.Emit(OpCodes.Ldloca_S, enumeratorLocal.LocalIndex);
il.Emit(OpCodes.Constrained, enumeratorLocal.LocalType);
il.Emit(OpCodes.Callvirt, IDisposableDisposeMethod);
il.Emit(OpCodes.Endfinally);
il.EndExceptionBlock();
il.MarkLabel(endEnumeratorLabel);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment