in src/Microsoft.Azure.WebJobs.Host/Bindings/BindingProviders/AsyncCollectorBindingProvider.cs [73:135]
private CollectorBindingPattern GetMode(ParameterInfo parameter)
{
Type parameterType = parameter.ParameterType;
if (parameterType.IsGenericType)
{
var genericType = parameterType.GetGenericTypeDefinition();
var elementType = parameterType.GetGenericArguments()[0];
if (genericType == typeof(IAsyncCollector<>))
{
return new CollectorBindingPattern(Mode.IAsyncCollector, elementType);
}
else if (genericType == typeof(ICollector<>))
{
return new CollectorBindingPattern(Mode.ICollector, elementType);
}
// A different interface. Let another rule try it.
return null;
}
if (parameter.IsOut)
{
// How should "out byte[]" bind?
// If there's an explicit "byte[] --> TMessage" converter, then that takes precedence.
// Else, bind over an array of "byte --> TMessage" converters
Type elementType = parameter.ParameterType.GetElementType();
bool hasConverter = this._converterManager.HasConverter<TAttribute>(elementType, typeof(TType));
if (hasConverter)
{
// out T, where T might be an array
return new CollectorBindingPattern(Mode.OutSingle, elementType);
}
if (elementType.IsArray)
{
// out T[]
var messageType = elementType.GetElementType();
return new CollectorBindingPattern(Mode.OutArray, messageType);
}
var validator = OpenType.FromType<TType>();
if (validator.IsMatch(elementType))
{
// out T, t is not an array
return new CollectorBindingPattern(Mode.OutSingle, elementType);
}
// For out-param ,we don't expect another rule to claim it. So give some rich errors on mismatch.
if (typeof(IEnumerable).IsAssignableFrom(elementType))
{
throw new InvalidOperationException(
"Enumerable types are not supported. Use ICollector<T> or IAsyncCollector<T> instead.");
}
else if (typeof(object) == elementType)
{
throw new InvalidOperationException("Object element types are not supported.");
}
}
// No match. Let another rule claim it
return null;
}