public override async IAsyncEnumerable <Path> ComputePaths(EvaluationContext ctx)
 {
     _entityPaths ??= EntityCandidate.ComputePaths(ctx);
     await foreach (var path in _entityPaths)
     {
         yield return(path.Append(PropertyName)); // <-- Best guess, since we don't know if the property is simple or nav
     }
 }
        public override async IAsyncEnumerable <Path> ComputeSelect(EvaluationContext ctx)
        {
            await foreach (var select in EntityCandidate.ComputeSelect(ctx))
            {
                yield return(select);
            }

            _entityPaths ??= EntityCandidate.ComputePaths(ctx);
            await foreach (var path in _entityPaths)
            {
                yield return(path.Append(PropertyName));
            }
        }
        public override async Task <object> Evaluate(EvaluationContext ctx)
        {
            var entityCandidate = await EntityCandidate.Evaluate(ctx);

            if (entityCandidate == null)
            {
                // Template property access implements null propagation out of the box
                return(null);
            }

            if (entityCandidate is Entity entity)
            {
                if (entity is EntityWithKey entityWithKey && PropertyName == "Id")
                {
                    return(entityWithKey.GetId());
                }

                var entityType = entity.GetType();
                var propInfo   = entityType.GetProperty(PropertyName);
                if (propInfo == null || propInfo.GetCustomAttribute <NotMappedAttribute>() != null)
                {
                    throw new TemplateException($"Property '{PropertyName}' does not exist on type {entityType.Name}.");
                }
                else if (!entity.EntityMetadata.TryGetValue(PropertyName, out FieldMetadata meta))
                {
                    // Developer mistake
                    throw new InvalidOperationException($"Property '{PropertyName}' on type {entityType.Name} was not loaded correctly.");
                }
                else if (meta == FieldMetadata.Restricted)
                {
                    throw new TemplateException($"Your account is not granted access to property '{PropertyName}' on type '{entityType.Name}'.");
                }
                else if (meta == FieldMetadata.Loaded)
                {
                    return(propInfo.GetValue(entity));
                }
                else
                {
                    // For future proofing
                    throw new InvalidOperationException($"Unknown FieldMetadata value '{meta}'.");
                }
            }
            else
            {
                throw new TemplateException($"Property access '.{PropertyName}' is only valid on model entities.");
            }
        }