예제 #1
0
        public static void Iterate(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            object target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            if (!HandlebarsUtils.IsTruthy(target))
            {
                using var frame = context.CreateFrame(context.Value);
                ifEmpty(writer, frame);
                return;
            }

            if (!ObjectDescriptor.TryCreate(target, context.Configuration.ObjectDescriptorProvider, out var descriptor))
            {
                throw new HandlebarsRuntimeException($"Cannot create ObjectDescriptor for type {descriptor.DescribedType}");
            }

            if (descriptor.Iterator == null)
            {
                throw new HandlebarsRuntimeException($"Type {descriptor.DescribedType} does not support iteration");
            }

            descriptor.Iterator.Iterate(writer, context, blockParamsVariables, target, template, ifEmpty);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        public static void Iterate(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            object target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            if (!HandlebarsUtils.IsTruthy(target))
            {
                using var frame = context.CreateFrame(context.Value);
                ifEmpty(writer, frame);
                return;
            }

            var targetType = target.GetType();

            if (!context.Configuration.ObjectDescriptorProvider.TryGetDescriptor(targetType, out var descriptor))
            {
                using var frame = context.CreateFrame(context.Value);
                ifEmpty(writer, frame);
                return;
            }

            if (!descriptor.ShouldEnumerate)
            {
                var properties = descriptor.GetProperties(descriptor, target);
                if (properties is IList <ChainSegment> propertiesList)
                {
                    IterateObjectWithStaticProperties(context, writer, blockParamsVariables, descriptor, target, propertiesList, targetType, template, ifEmpty);
                    return;
                }

                IterateObject(context, writer, descriptor, blockParamsVariables, target, properties, targetType, template, ifEmpty);
                return;
            }

            if (target is IList list)
            {
                IterateList(context, writer, blockParamsVariables, list, template, ifEmpty);
                return;
            }

            IterateEnumerable(context, writer, blockParamsVariables, (IEnumerable)target, template, ifEmpty);
        }
예제 #5
0
        private static void IterateEnumerable(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            IEnumerable target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new IteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

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

            var enumerator = new ExtendedEnumerator <object>(target.GetEnumerator());
            var enumerated = false;

            object boxedIndex;
            object iteratorValue;

            while (enumerator.MoveNext())
            {
                enumerated = true;
                var enumerableValue = enumerator.Current;

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

                boxedIndex     = enumerableValue.Index;
                iteratorValue  = enumerableValue.Value;
                iterator.Value = iteratorValue;
                iterator.Index = boxedIndex;

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

                innerContext.Value = iteratorValue;

                template(writer, innerContext);
            }

            if (!enumerated)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
예제 #6
0
        private static void IterateList(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            IList target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new IteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

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

            var count = target.Count;

            object boxedIndex;
            object iteratorValue;

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

            for (; iterationIndex < count; iterationIndex++)
            {
                iteratorValue = target[iterationIndex];

                iterator.Value = iteratorValue;
                if (iterationIndex == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (iterationIndex == lastIndex)
                {
                    iterator.Last = BoxedValues.True;
                }

                boxedIndex     = iterationIndex;
                iterator.Index = boxedIndex;

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

                innerContext.Value = iteratorValue;

                template(writer, innerContext);
            }

            if (iterationIndex == 0)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        private static void RenderSection(object value,
                                          BindingContext context,
                                          EncodedTextWriter writer,
                                          TemplateDelegate body,
                                          TemplateDelegate inversion)
        {
            switch (value)
            {
            case bool boolValue when boolValue:
                body(writer, context);
                return;

            case null:
            case object _ when HandlebarsUtils.IsFalsyOrEmpty(value):
                inversion(writer, context);

                return;

            case string _:
            {
                using var frame = context.CreateFrame(value);
                body(writer, frame);
                return;
            }

            case IEnumerable enumerable:
                Iterator.Iterate(context, writer, BlockParamsVariables, enumerable, body, inversion);
                break;

            default:
            {
                using var frame = context.CreateFrame(value);
                body(writer, frame);
                break;
            }
            }
        }