in src/Microsoft.Azure.WebJobs.Host/Bindings/BindingProviders/AsyncCollectorBindingProvider.cs [264:330]
public static ExactBinding<TMessage> TryBuild(
AsyncCollectorBindingProvider<TAttribute, TType> parent,
Mode mode,
BindingProviderContext context)
{
var patternMatcher = parent._patternMatcher;
var parameter = context.Parameter;
var attributeSource = TypeUtility.GetResolvedAttribute<TAttribute>(parameter);
FuncAsyncConverter buildFromAttribute;
FuncAsyncConverter<TMessage, TType> converter = null;
// Prefer the shortest route to creating the user type.
// If TType matches the user type directly, then we should be able to directly invoke the builder in a single step.
// TAttribute --> TUserType
var checker = OpenType.FromType<TType>();
if (checker.IsMatch(typeof(TMessage)))
{
buildFromAttribute = patternMatcher.TryGetConverterFunc(
typeof(TAttribute), typeof(IAsyncCollector<TMessage>));
}
else
{
var converterManager = parent._converterManager;
// Try with a converter
// Find a builder for : TAttribute --> TType
// and then couple with a converter: TType --> TParameterType
converter = converterManager.GetConverter<TMessage, TType, TAttribute>();
if (converter == null)
{
// Preserves legacy behavior. This means we can only have 1 async collector.
// However, the collector's builder object can switch.
throw NewMissingConversionError(typeof(TMessage));
}
buildFromAttribute = patternMatcher.TryGetConverterFunc(
typeof(TAttribute), typeof(IAsyncCollector<TType>));
}
if (buildFromAttribute == null)
{
context.BindingErrors.Add(String.Format(Resource.BindingAssemblyConflictMessage, typeof(TType).AssemblyQualifiedName, typeof(TMessage).AssemblyQualifiedName));
return null;
}
ParameterDescriptor param;
if (parent.BuildParameterDescriptor != null)
{
param = parent.BuildParameterDescriptor(attributeSource, parameter, parent._nameResolver);
}
else
{
param = new ParameterDescriptor
{
Name = parameter.Name,
DisplayHints = new ParameterDisplayHints
{
Description = "output"
}
};
}
var cloner = new AttributeCloner<TAttribute>(attributeSource, context.BindingDataContract, parent._configuration, parent._nameResolver);
return new ExactBinding<TMessage>(cloner, param, mode, buildFromAttribute, converter);
}