private LocalILCodeVariable GenerateDictionaryEnumerateCode(Type type, string refName)
        {
            var extType = _il.TypeCache.Extend(type);
            var dictionaryMembers = new DictionaryMembers(extType);

            var local = _il.DeclareLocal("dictionary", dictionaryMembers.VariableType);
            _il.Construct(dictionaryMembers.Constructor);
            _il.Var.Set(local);

            NullableMembers keyNullableMembers;
            ILCodeParameter keyParam;

            var conditionLabel = _il.DefineLabel();
            var bodyLabel = _il.DefineLabel();
            var keyType = Members.Nullable.TryGetValue(dictionaryMembers.KeyType, out keyNullableMembers) ? keyNullableMembers.NullableType : dictionaryMembers.KeyType;
            var keyTypeExt = _il.TypeCache.Extend(keyType);

            // First of all, transfer to the condition part
            _il.TransferLong(conditionLabel);

            // Mark that we enter the body of the loop
            _il.MarkLabel(bodyLabel);
            if (keyTypeExt.IsValueOrNullableOfValue()) {
                keyParam = _il.DeclareLocal("ck", keyType);
            }
            else if (keyTypeExt.Class == TypeClass.Dictionary) {
                keyParam = GenerateDictionaryEnumerateCode(keyType, refName);

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryKey);
            }
            else if (keyTypeExt.Class == TypeClass.Collection) {
                keyParam = GenerateCollectionContent(keyTypeExt, refName);

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryKey);
            }
            else {
                var keyLocal = _il.DeclareLocal("ck", keyType);
                GenerateCreateAndChildCallCode(keyLocal);
                keyParam = keyLocal;
                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryKey);
            }

            var throwExceptionLabel = _il.DefineLabel();

            ILCodeParameter valueParam;

            NullableMembers valueNullableMembers;
            var hasNullableMembers = Members.Nullable.TryGetValue(dictionaryMembers.ValueType, out valueNullableMembers);
            var valueType = dictionaryMembers.ValueType;
            var extValueType = valueType.Extend();

            if (extValueType.IsValueOrNullableOfValue()) {
                var loadTrueLabel = _il.DefineLabel();
                var checkIfErrorLabel = _il.DefineLabel();

                valueParam = _il.DeclareLocal("cv", hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[dictionaryMembers.ValueType], Members.VisitArgsDictionaryValue, valueParam);
                _il.TransferLongIfFalse(loadTrueLabel);

                if (hasNullableMembers) {
                    _il.Snippets.InvokeMethod(valueParam, valueNullableMembers.GetHasValue);
                    _il.Negate();
                }
                else {
                    _il.Snippets.AreEqual(valueParam, null);
                }
                _il.TransferLong(checkIfErrorLabel);
                _il.MarkLabel(loadTrueLabel);
                _il.LoadValue(true);
                _il.MarkLabel(checkIfErrorLabel);
                _il.TransferLongIfTrue(throwExceptionLabel);
            }
            else if (extValueType.Class == TypeClass.Dictionary) {
                var callTryVisitValue = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryValue);
                _il.Snippets.AreEqual(callTryVisitValue, (int)ValueState.Found);
                _il.TransferLongIfFalse(throwExceptionLabel);

                valueParam = GenerateDictionaryEnumerateCode(valueType, refName);

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryValue);
            }
            else if (extValueType.Class == TypeClass.Collection) {
                var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryValue);
                _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                _il.TransferLongIfFalse(throwExceptionLabel);

                valueParam = GenerateCollectionContent(_il.TypeCache.Extend(valueType), refName);

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryValue);
            }
            else {
                var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryValue);
                _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                _il.TransferLongIfFalse(throwExceptionLabel);

                var valueLocal = _il.DeclareLocal("cv", hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                GenerateCreateAndChildCallCode(valueLocal);
                valueParam = valueLocal;

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryValue);
            }

            _il.Var.Load(local);
            GenerateLoadParamValueCode(keyParam);
            GenerateLoadParamValueCode(valueParam);

            _il.CallVirt(dictionaryMembers.Add);
            _il.TransferLong(conditionLabel);

            _il.MarkLabel(throwExceptionLabel);
            _il.Snippets.Throw(new CallMethodILCode(Members.ExceptionNoDictionaryValue, refName));

            _il.MarkLabel(conditionLabel);

            if (keyTypeExt.IsValueOrNullableOfValue()) {
                var loadZeroLabel = _il.DefineLabel();
                var checkConditionLabel = _il.DefineLabel();

                _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[keyType], Members.VisitArgsDictionaryKey, keyParam);
                _il.TransferLongIfFalse(loadZeroLabel);

                if (keyType.IsValueType) {
                    _il.Snippets.InvokeMethod(keyParam, Members.Nullable[keyType].GetHasValue);
                    _il.TransferLong(checkConditionLabel);
                }
                else {
                    _il.Snippets.AreEqual(keyParam, ILCodeParameter.Null);
                    _il.Negate();
                    _il.TransferLong(checkConditionLabel);
                }

                _il.MarkLabel(loadZeroLabel);
                _il.LoadValue(false);
                _il.MarkLabel(checkConditionLabel);
                _il.TransferLongIfTrue(bodyLabel);

            }
            else if (keyTypeExt.Class == TypeClass.Dictionary) {
                var callTryVisitKey = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryKey);
                _il.Snippets.AreEqual(callTryVisitKey, (int)ValueState.Found);
                _il.TransferLongIfTrue(bodyLabel);
            }
            else if (keyTypeExt.Class == TypeClass.Collection) {
                var callTryVisitKey = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryKey);
                _il.Snippets.AreEqual(callTryVisitKey, (int)ValueState.Found);
                _il.TransferLongIfTrue(bodyLabel);
            }
            else {
                var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryKey);
                _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                _il.TransferLongIfTrue(bodyLabel);
            }

            return local;
        }
        private ILLocalVariable GenerateDictionaryEnumerateCode(Type type, string refName)
        {
            var extType           = _typeProvider.Extend(type);
            var dictionaryMembers = new DictionaryMembers(extType);

            var local = _il.NewLocal(dictionaryMembers.VariableType);

            _il.Construct(dictionaryMembers.Constructor);
            _il.Set(local);

            var keyType = Members.Nullable.TryGetValue(dictionaryMembers.KeyType, out var keyNullableMembers)
                ? keyNullableMembers.NullableType
                : dictionaryMembers.KeyType;

            var conditionLabel = _il.NewLabel();
            var bodyLabel      = _il.NewLabel();

            var keyTypeExt = _typeProvider.Extend(keyType);

            // First of all, transfer to the condition part
            conditionLabel.TransferLong();

            // Mark that we enter the body of the loop
            bodyLabel.Mark();
            ILPointer keyParam;

            if (keyTypeExt.IsValueOrNullableOfValue())
            {
                keyParam = _il.NewLocal(keyType);
            }
            else if (keyTypeExt.Classification == TypeClassification.Dictionary)
            {
                keyParam = GenerateDictionaryEnumerateCode(keyType, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryKey);
            }
            else if (keyTypeExt.Classification == TypeClassification.Collection)
            {
                keyParam = GenerateCollectionContent(keyTypeExt, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryKey);
            }
            else
            {
                var keyLocal = _il.NewLocal(keyType);
                GenerateCreateAndChildCallCode(keyLocal);
                keyParam = keyLocal;
                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryKey);
            }

            var throwExceptionLabel = _il.NewLabel();

            var hasNullableMembers = Members.Nullable.TryGetValue(
                dictionaryMembers.ValueType, out var valueNullableMembers);
            var valueType    = dictionaryMembers.ValueType;
            var extValueType = _typeProvider.Extend(valueType);

            ILPointer valueParam;

            if (extValueType.IsValueOrNullableOfValue())
            {
                var loadTrueLabel     = _il.NewLabel();
                var checkIfErrorLabel = _il.NewLabel();

                valueParam = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[dictionaryMembers.ValueType], Members.VisitArgsDictionaryValue, valueParam);
                loadTrueLabel.TransferLongIfFalse();

                if (hasNullableMembers)
                {
                    _il.InvokeMethod(valueParam, valueNullableMembers.GetHasValue);
                    _il.Negate();
                }
                else
                {
                    _il.AreEqual(valueParam, null);
                }
                checkIfErrorLabel.TransferLong();
                loadTrueLabel.Mark();
                _il.Load(true);
                checkIfErrorLabel.Mark();
                throwExceptionLabel.TransferLongIfTrue();
            }
            else if (extValueType.Classification == TypeClassification.Dictionary)
            {
                var callTryVisitValue = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryValue);
                _il.AreEqual(callTryVisitValue, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                valueParam = GenerateDictionaryEnumerateCode(valueType, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryValue);
            }
            else if (extValueType.Classification == TypeClassification.Collection)
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryValue);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                valueParam = GenerateCollectionContent(_typeProvider.Extend(valueType), refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryValue);
            }
            else
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryValue);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                var valueLocal = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                GenerateCreateAndChildCallCode(valueLocal);
                valueParam = valueLocal;

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryValue);
            }

            _il.Load(local);
            GenerateLoadParamValueCode(keyParam);
            GenerateLoadParamValueCode(valueParam);

            _il.EmitCall(OpCodes.Callvirt, dictionaryMembers.Add, null);
            conditionLabel.TransferLong();

            throwExceptionLabel.Mark();
            _il.Throw(new ILCallMethodSnippet(Members.ExceptionNoDictionaryValue, refName));

            conditionLabel.Mark();

            if (keyTypeExt.IsValueOrNullableOfValue())
            {
                var loadZeroLabel       = _il.NewLabel();
                var checkConditionLabel = _il.NewLabel();

                _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[keyType], Members.VisitArgsDictionaryKey, keyParam);
                loadZeroLabel.TransferLongIfFalse();

                if (keyTypeExt.Info.IsValueType)
                {
                    _il.InvokeMethod(keyParam, Members.Nullable[keyType].GetHasValue);
                    checkConditionLabel.TransferLong();
                }
                else
                {
                    _il.AreEqual(keyParam, ILPointer.Null);
                    _il.Negate();
                    checkConditionLabel.TransferLong();
                }

                loadZeroLabel.Mark();
                _il.Load(false);
                checkConditionLabel.Mark();
                bodyLabel.TransferLongIfTrue();
            }
            else if (keyTypeExt.Classification == TypeClassification.Dictionary)
            {
                var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryKey);
                _il.AreEqual(callTryVisitKey, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }
            else if (keyTypeExt.Classification == TypeClassification.Collection)
            {
                var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryKey);
                _il.AreEqual(callTryVisitKey, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }
            else
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryKey);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }

            return(local);
        }