public bool TryGetHeaderInitializer <TProperty>(PropertyInfo propertyInfo, out IHeaderInitializer <TMessage, TInput> initializer)
        {
            var propertyName = propertyInfo?.Name ?? throw new ArgumentNullException(nameof(propertyInfo));

            // headers use a double underscore prefix
            string inputPropertyName = new StringBuilder(propertyName.Length + 2).Append("__").Append(propertyName).ToString();

            if (_inputProperties.TryGetValue(inputPropertyName, out var inputPropertyInfo))
            {
                var propertyType      = typeof(TProperty);
                var inputPropertyType = inputPropertyInfo.PropertyType;

                // exactly the same type, we just copy it over unmodified
                if (inputPropertyType == propertyType)
                {
                    initializer = new CopyHeaderInitializer <TMessage, TInput, TProperty>(propertyInfo, inputPropertyInfo);
                    return(true);
                }

                if (_providerFactory.TryGetPropertyProvider(inputPropertyInfo, out IPropertyProvider <TInput, TProperty> provider))
                {
                    initializer = new ProviderHeaderInitializer <TMessage, TInput, TProperty>(provider, propertyInfo);
                    return(true);
                }
            }

            initializer = default;
            return(false);
        }
        public bool TryGetHeaderInitializer <TProperty>(string propertyName, out IHeaderInitializer <TMessage, TInput> initializer)
        {
            // headers use a double underscore prefix

            string inputPropertyName = new StringBuilder(propertyName.Length + 2).Append("__").Append(propertyName).ToString();

            var inputPropertyInfo = typeof(TInput).GetProperty(inputPropertyName);

            if (inputPropertyInfo != null)
            {
                var propertyType      = typeof(TProperty);
                var inputPropertyType = inputPropertyInfo.PropertyType;

                // exactly the same type, we just copy it over unmodified
                if (inputPropertyType == propertyType)
                {
                    initializer = new CopyHeaderInitializer <TMessage, TInput, TProperty>(propertyName, inputPropertyName);
                    return(true);
                }

                if (PropertyInitializerCache.TryGetFactory <TProperty>(inputPropertyType, out var propertyConverter))
                {
                    initializer = propertyConverter.CreateHeaderInitializer <TMessage, TInput>(propertyName, inputPropertyName);
                    return(true);
                }
            }

            initializer = default;
            return(false);
        }