BTDB.EventStoreLayer.DictionaryTypeDescriptor.TypeNewDescriptorGenerator.GenerateTypeIterator C# (CSharp) Method

GenerateTypeIterator() public method

public GenerateTypeIterator ( IILGen ilGenerator, Action pushObj, Action pushCtx, Type type ) : void
ilGenerator IILGen
pushObj Action
pushCtx Action
type System.Type
return void
            public void GenerateTypeIterator(IILGen ilGenerator, Action<IILGen> pushObj, Action<IILGen> pushCtx, Type type)
            {
                var finish = ilGenerator.DefineLabel();
                var next = ilGenerator.DefineLabel();
                var keyType = _owner._typeSerializers.LoadAsType(_owner._keyDescriptor);
                var valueType = _owner._typeSerializers.LoadAsType(_owner._valueDescriptor);
                if (_owner._type == null) _owner._type = type;
                var isDict = _owner._type != null && _owner._type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
                var typeAsIDictionary = isDict ? _owner._type : typeof(IDictionary<,>).MakeGenericType(keyType, valueType);
                var getEnumeratorMethod = isDict
                    ? typeAsIDictionary.GetMethods()
                        .Single(
                            m => m.Name == "GetEnumerator" && m.ReturnType.IsValueType && m.GetParameters().Length == 0)
                    : 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);
                ilGenerator
                    .Do(pushObj)
                    .Castclass(typeAsIDictionary)
                    .Callvirt(getEnumeratorMethod)
                    .Stloc(localEnumerator)
                    .Try()
                    .Mark(next)
                    .Do(il =>
                    {
                        if (isDict)
                        {
                            il
                                .Ldloca(localEnumerator)
                                .Call(typeAsIEnumerator.GetMethod("MoveNext"));
                        }
                        else
                        {
                            il
                                .Ldloc(localEnumerator)
                                .Callvirt(() => default(IEnumerator).MoveNext());
                        }
                    })
                    .Brfalse(finish)
                    .Do(il =>
                    {
                        if (isDict)
                        {
                            il
                                .Ldloca(localEnumerator)
                                .Call(currentGetter);
                        }
                        else
                        {
                            il
                                .Ldloc(localEnumerator)
                                .Callvirt(currentGetter);
                        }
                    })
                    .Stloc(localPair);
                if (!_owner._keyDescriptor.Sealed)
                {
                    ilGenerator
                        .Do(pushCtx)
                        .Ldloca(localPair)
                        .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod())
                        .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null));
                }
                if (!_owner._valueDescriptor.Sealed)
                {
                    ilGenerator
                        .Do(pushCtx)
                        .Ldloca(localPair)
                        .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod())
                        .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null));
                }
                ilGenerator
                    .Br(next)
                    .Mark(finish)
                    .Finally()
                    .Do(il =>
                    {
                        if (isDict)
                        {
                            il
                                .Ldloca(localEnumerator)
                                .Constrained(typeAsIEnumerator);
                        }
                        else
                        {
                            il.Ldloc(localEnumerator);
                        }
                    })
                    .Callvirt(() => default(IDisposable).Dispose())
                    .EndTry();
            }
DictionaryTypeDescriptor.TypeNewDescriptorGenerator