private IEnumerable <ActivityPropertyDescriptor> DescribeProperties(Type activityType)
        {
            var properties = activityType.GetProperties();

            foreach (var propertyInfo in properties)
            {
                var activityPropertyAttribute = propertyInfo.GetCustomAttribute <ActivityPropertyAttribute>();

                if (activityPropertyAttribute == null)
                {
                    continue;
                }

                yield return(new ActivityPropertyDescriptor
                             (
                                 (activityPropertyAttribute.Name ?? propertyInfo.Name).Pascalize(),
                                 propertyInfo.PropertyType,
                                 _uiHintResolver.GetUIHint(propertyInfo),
                                 activityPropertyAttribute.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
                                 activityPropertyAttribute.Hint,
                                 _optionsResolver.GetOptions(propertyInfo),
                                 activityPropertyAttribute.Category,
                                 _defaultValueResolver.GetDefaultValue(propertyInfo),
                                 activityPropertyAttribute.DefaultSyntax,
                                 activityPropertyAttribute.SupportedSyntaxes
                             ));
            }
        }
        private IEnumerable <ActivityInputDescriptor> DescribeInputProperties(IEnumerable <PropertyInfo> properties)
        {
            foreach (var propertyInfo in properties)
            {
                var activityPropertyAttribute = propertyInfo.GetCustomAttribute <ActivityInputAttribute>();

                if (activityPropertyAttribute == null)
                {
                    continue;
                }

                yield return(new ActivityInputDescriptor
                             (
                                 activityPropertyAttribute.Name ?? propertyInfo.Name,
                                 propertyInfo.PropertyType,
                                 _uiHintResolver.GetUIHint(propertyInfo),
                                 activityPropertyAttribute.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
                                 activityPropertyAttribute.Hint,
                                 _optionsResolver.GetOptions(propertyInfo),
                                 activityPropertyAttribute.Category,
                                 activityPropertyAttribute.Order,
                                 _defaultValueResolver.GetDefaultValue(propertyInfo),
                                 activityPropertyAttribute.DefaultSyntax,
                                 activityPropertyAttribute.SupportedSyntaxes,
                                 activityPropertyAttribute.IsReadOnly ?? false,
                                 activityPropertyAttribute.IsBrowsable ?? true,
                                 activityPropertyAttribute.IsDesignerCritical,
                                 activityPropertyAttribute.DefaultWorkflowStorageProvider,
                                 activityPropertyAttribute.DisableWorkflowProviderSelection
                             ));
            }
        }
        private IEnumerable <ActivityInputDescriptor> DescribeInputProperties(IEnumerable <PropertyInfo> properties, string category = null)
        {
            foreach (var propertyInfo in properties)
            {
                var activityPropertyObjectAttribute = propertyInfo.GetCustomAttribute <ActivityInputObjectAttribute>();

                if (activityPropertyObjectAttribute != null)
                {
                    var objectProperties = propertyInfo.PropertyType.GetProperties();

                    var nestedInputProperties = DescribeInputProperties(objectProperties, activityPropertyObjectAttribute?.Category);

                    foreach (var property in nestedInputProperties)
                    {
                        property.Name = $"{propertyInfo.Name}_{property.Name}";
                        yield return(property);
                    }
                    continue;
                }

                var activityPropertyAttribute = propertyInfo.GetCustomAttribute <ActivityInputAttribute>();

                if (activityPropertyAttribute == null)
                {
                    continue;
                }

                yield return(new ActivityInputDescriptor
                             (
                                 activityPropertyAttribute.Name ?? propertyInfo.Name,
                                 propertyInfo.PropertyType,
                                 _uiHintResolver.GetUIHint(propertyInfo),
                                 activityPropertyAttribute.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
                                 activityPropertyAttribute.Hint,
                                 _optionsResolver.GetOptions(propertyInfo),
                                 activityPropertyAttribute.Category ?? category,
                                 activityPropertyAttribute.Order,
                                 _defaultValueResolver.GetDefaultValue(propertyInfo),
                                 activityPropertyAttribute.DefaultSyntax,
                                 activityPropertyAttribute.SupportedSyntaxes,
                                 activityPropertyAttribute.IsReadOnly,
                                 activityPropertyAttribute.IsBrowsable,
                                 activityPropertyAttribute.IsDesignerCritical,
                                 activityPropertyAttribute.DefaultWorkflowStorageProvider,
                                 activityPropertyAttribute.DisableWorkflowProviderSelection,
                                 activityPropertyAttribute.ConsiderValuesAsOutcomes
                             ));
            }
        }
        private async ValueTask SetNestedActivityPropertiesAsync(object nestedInstance, ActivityExecutionContext activityExecutionContext, IDictionary <string, IActivityPropertyValueProvider> providers, IActivityPropertyDefaultValueResolver defaultValueResolver, string nestedInstanceName = null, CancellationToken cancellationToken = default)
        {
            var properties       = nestedInstance.GetType().GetProperties().Where(IsActivityInputProperty).ToList();
            var nestedProperties = nestedInstance.GetType().GetProperties().Where(IsActivityObjectInputProperty).ToList();

            foreach (var property in properties)
            {
                var propertyName = nestedInstanceName == null ? property.Name : $"{nestedInstanceName}_{property.Name}";
                if (!providers.TryGetValue(propertyName, out var provider))
                {
                    continue;
                }

                try
                {
                    var value = await provider.GetValueAsync(activityExecutionContext, cancellationToken);

                    if (value == null)
                    {
                        value = defaultValueResolver.GetDefaultValue(property);
                    }

                    if (value != null)
                    {
                        property.SetValue(nestedInstance, value);
                    }
                }
                catch (Exception e)
                {
                    throw new CannotSetActivityPropertyValueException($@"An exception was thrown whilst setting '{nestedInstance.GetType().Name}.{property.Name}'. See the inner exception for further details.", e);
                }
            }

            foreach (var nestedProperty in nestedProperties)
            {
                var instance = Activator.CreateInstance(nestedProperty.PropertyType);

                var nextInstanceName = nestedInstanceName == null ? nestedProperty.Name : $"{nestedInstanceName}_{nestedProperty.Name}";

                await SetNestedActivityPropertiesAsync(instance, activityExecutionContext, providers, defaultValueResolver, nextInstanceName, cancellationToken);

                nestedProperty.SetValue(nestedInstance, instance);
            }
        }