public void Save(IILGen ilGenerator, Action<IILGen> pushWriterOrCtx, Action<IILGen> pushValue)
{
var realfinish = ilGenerator.DefineLabel();
var finish = ilGenerator.DefineLabel();
var next = ilGenerator.DefineLabel();
var localValue = ilGenerator.DeclareLocal(_type);
var typeAsICollection = _type.GetInterface("ICollection`1");
var typeAsIEnumerable = _type.GetInterface("IEnumerable`1");
var getEnumeratorMethod = typeAsIEnumerable.GetMethod("GetEnumerator");
var typeAsIEnumerator = getEnumeratorMethod.ReturnType;
var typeKeyValuePair = typeAsICollection.GetGenericArguments()[0];
var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator);
var localPair = ilGenerator.DeclareLocal(typeKeyValuePair);
ilGenerator
.Do(pushValue)
.Stloc(localValue)
.Do(pushWriterOrCtx)
.Ldloc(localValue)
.Castclass(typeof(object))
.Callvirt(() => default(IWriterCtx).WriteObject(null))
.Brfalse(realfinish)
.Do(Extensions.PushWriterFromCtx(pushWriterOrCtx))
.Ldloc(localValue)
.Callvirt(typeAsICollection.GetProperty("Count").GetGetMethod())
.ConvU4()
.Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0))
.Ldloc(localValue)
.Callvirt(getEnumeratorMethod)
.Stloc(localEnumerator)
.Try()
.Mark(next)
.Ldloc(localEnumerator)
.Callvirt(() => default(IEnumerator).MoveNext())
.Brfalse(finish)
.Ldloc(localEnumerator)
.Callvirt(typeAsIEnumerator.GetProperty("Current").GetGetMethod())
.Stloc(localPair);
_keysHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _keysHandler.NeedsCtx()), il => il
.Ldloca(localPair)
.Call(typeKeyValuePair.GetProperty("Key").GetGetMethod())
.Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _keysHandler.HandledType())));
_valuesHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _valuesHandler.NeedsCtx()), il => il
.Ldloca(localPair)
.Call(typeKeyValuePair.GetProperty("Value").GetGetMethod())
.Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[1], _valuesHandler.HandledType())));
ilGenerator
.Br(next)
.Mark(finish)
.Finally()
.Ldloc(localEnumerator)
.Callvirt(() => default(IDisposable).Dispose())
.EndTry()
.Mark(realfinish);
}