public ConstructorInfo CreateEnumeratorType(Type propertyType, IReadOnlyList <FieldBuilder> fieldStates, IReadOnlyDictionary <string, ModelPropertyTypeGenerator.Field> fields)
        {
            var typeBuilder = _moduleBuilder.DefineUniqueType("ModelPropertiesEnumerator");

            var groupedFields = fieldStates.Select(fs => (FieldState: fs, Fields: (IReadOnlyList <ModelPropertyTypeGenerator.Field>)fields.Values.Where(f => f.State.Field == fs).OrderBy(f => f.State.Offset).ToList())).ToList();

            var enumeratorFields = new EnumeratorFields(typeBuilder, propertyType, fieldStates);
            var constructor      = ImplementConstructor(typeBuilder, propertyType, enumeratorFields, fieldStates);

            typeBuilder.AddInterfaceImplementation(typeof(IEnumerator <KeyValuePair <string, object> >));
            ImplementEnumerator(typeBuilder, enumeratorFields, groupedFields);
            ImplementDisposable(typeBuilder);

            typeBuilder.CreateTypeInfo();

            return(constructor);
        }
 private static void ImplementEnumerator(TypeBuilder typeBuilder, EnumeratorFields enumeratorFields, IReadOnlyList <(FieldBuilder FieldState, IReadOnlyList <ModelPropertyTypeGenerator.Field> Fields)> fields)
        private static ConstructorInfo ImplementConstructor(TypeBuilder typeBuilder, Type propertyType, EnumeratorFields enumeratorFields, IReadOnlyList <FieldBuilder> fieldStates)
        {
            var types = new Type[1 + fieldStates.Count];

            types[0] = propertyType;
            for (var index = 0; index < fieldStates.Count; index++)
            {
                types[1 + index] = typeof(BitVector32);
            }

            var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, types);

            constructorBuilder.DefineParameter(1, ParameterAttributes.None, "properties");
            for (var index = 0; index < fieldStates.Count; index++)
            {
                constructorBuilder.DefineParameter(2 + index, ParameterAttributes.None, $"fieldState{index}");
            }
            var il = constructorBuilder.GetILGenerator();

            // this._properties = properties;
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Stfld, enumeratorFields.Properties);

            for (var index = 0; index < fieldStates.Count; index++)
            {
                var fieldState = fieldStates[index];
                // this._fieldState{i} = fieldState{i};
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg, 2 + index);
                il.Emit(OpCodes.Stfld, enumeratorFields.FieldStatesMap[fieldState]);
            }

            il.Emit(OpCodes.Ret);

            return(constructorBuilder);
        }