private static void IterateObjectWithStaticProperties(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            ObjectDescriptor descriptor,
            object target,
            IList <ChainSegment> properties,
            Type targetType,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new ObjectIteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var count    = properties.Count;
            var accessor = new MemberAccessor(target, descriptor);

            var iterationIndex = 0;
            var lastIndex      = count - 1;

            object       iteratorValue;
            ChainSegment iteratorKey;

            for (; iterationIndex < count; iterationIndex++)
            {
                iteratorKey = properties[iterationIndex];

                iterator.Index = iterationIndex;
                iterator.Key   = iteratorKey;
                if (iterationIndex == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (iterationIndex == lastIndex)
                {
                    iterator.Last = BoxedValues.True;
                }

                iteratorValue      = accessor[iteratorKey];
                iterator.Value     = iteratorValue;
                innerContext.Value = iteratorValue;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = iteratorKey;

                template(writer, innerContext);
            }

            if (iterationIndex == 0)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        private static void IterateObject(
            BindingContext context,
            EncodedTextWriter writer,
            ObjectDescriptor descriptor,
            ChainSegment[] blockParamsVariables,
            object target,
            IEnumerable properties,
            Type targetType,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new ObjectIteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var accessor   = new MemberAccessor(target, descriptor);
            var enumerable = new ExtendedEnumerator <object>(properties.GetEnumerator());
            var enumerated = false;

            object       iteratorValue;
            ChainSegment iteratorKey;

            while (enumerable.MoveNext())
            {
                enumerated = true;
                var enumerableValue = enumerable.Current;
                iteratorKey = ChainSegment.Create(enumerableValue.Value);

                iterator.Key   = iteratorKey;
                iterator.Index = enumerableValue.Index;
                if (enumerableValue.Index == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (enumerableValue.IsLast)
                {
                    iterator.Last = BoxedValues.True;
                }

                iteratorValue      = accessor[iteratorKey];
                iterator.Value     = iteratorValue;
                innerContext.Value = iteratorValue;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = iteratorKey;

                template(writer, innerContext);
            }

            if (!enumerated)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }