BTDB.EventStoreLayer.DictionaryTypeDescriptor.GenerateSave C# (CSharp) Метод

GenerateSave() публичный Метод

public GenerateSave ( IILGen ilGenerator, Action pushWriter, Action pushCtx, Action pushValue, Type saveType ) : void
ilGenerator IILGen
pushWriter Action
pushCtx Action
pushValue Action
saveType System.Type
Результат void
        public void GenerateSave(IILGen ilGenerator, Action<IILGen> pushWriter, Action<IILGen> pushCtx,
            Action<IILGen> pushValue, Type saveType)
        {
            var notnull = ilGenerator.DefineLabel();
            var completeFinish = ilGenerator.DefineLabel();
            var notDictionary = ilGenerator.DefineLabel();
            var keyType = saveType.GetGenericArguments()[0];
            var valueType = saveType.GetGenericArguments()[1];
            var typeAsIDictionary = typeof(IDictionary<,>).MakeGenericType(keyType, valueType);
            var typeAsICollection = typeAsIDictionary.GetInterface("ICollection`1");
            var localDict = ilGenerator.DeclareLocal(typeAsIDictionary);
            ilGenerator
                .Do(pushValue)
                .Castclass(typeAsIDictionary)
                .Stloc(localDict)
                .Ldloc(localDict)
                .Brtrue(notnull)
                .Do(pushWriter)
                .Callvirt(() => default(AbstractBufferedWriter).WriteByteZero())
                .Br(completeFinish)
                .Mark(notnull)
                .Do(pushWriter)
                .Ldloc(localDict)
                .Callvirt(typeAsICollection.GetProperty("Count").GetGetMethod())
                .LdcI4(1)
                .Add()
                .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0));
            {
                var typeAsDictionary = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
                var getEnumeratorMethod = typeAsDictionary.GetMethods()
                        .Single(m => m.Name == "GetEnumerator" && m.ReturnType.IsValueType && m.GetParameters().Length == 0);
                var typeAsIEnumerator = getEnumeratorMethod.ReturnType;
                var currentGetter = typeAsIEnumerator.GetProperty("Current").GetGetMethod();
                var typeKeyValuePair = currentGetter.ReturnType;
                var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator);
                var localPair = ilGenerator.DeclareLocal(typeKeyValuePair);
                var finish = ilGenerator.DefineLabel();
                var next = ilGenerator.DefineLabel();
                ilGenerator
                    .Ldloc(localDict)
                    .Castclass(typeAsDictionary)
                    .Brfalse(notDictionary)
                    .Ldloc(localDict)
                    .Castclass(typeAsDictionary)
                    .Callvirt(getEnumeratorMethod)
                    .Stloc(localEnumerator)
                    .Try()
                    .Mark(next)
                    .Ldloca(localEnumerator)
                    .Call(typeAsIEnumerator.GetMethod("MoveNext"))
                    .Brfalse(finish)
                    .Ldloca(localEnumerator)
                    .Call(currentGetter)
                    .Stloc(localPair);
                _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx,
                    il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType);
                _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx,
                    il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType);
                ilGenerator
                    .Br(next)
                    .Mark(finish)
                    .Finally()
                    .Ldloca(localEnumerator)
                    .Constrained(typeAsIEnumerator)
                    .Callvirt(() => default(IDisposable).Dispose())
                    .EndTry()
                    .Br(completeFinish);
            }
            {
                var getEnumeratorMethod = typeAsIDictionary.GetInterface("IEnumerable`1").GetMethod("GetEnumerator");
                var typeAsIEnumerator = getEnumeratorMethod.ReturnType;
                var currentGetter = typeAsIEnumerator.GetProperty("Current").GetGetMethod();
                var typeKeyValuePair = currentGetter.ReturnType;
                var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator);
                var localPair = ilGenerator.DeclareLocal(typeKeyValuePair);
                var finish = ilGenerator.DefineLabel();
                var next = ilGenerator.DefineLabel();
                ilGenerator
                    .Mark(notDictionary)
                    .Ldloc(localDict)
                    .Callvirt(getEnumeratorMethod)
                    .Stloc(localEnumerator)
                    .Try()
                    .Mark(next)
                    .Ldloc(localEnumerator)
                    .Callvirt(() => default(IEnumerator).MoveNext())
                    .Brfalse(finish)
                    .Ldloc(localEnumerator)
                    .Callvirt(currentGetter)
                    .Stloc(localPair);
                _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType);
                _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType);
                ilGenerator
                    .Br(next)
                    .Mark(finish)
                    .Finally()
                    .Ldloc(localEnumerator)
                    .Callvirt(() => default(IDisposable).Dispose())
                    .EndTry()
                    .Mark(completeFinish);
            }
        }