in src/Google.Cloud.Functions.Hosting/HostingInternals.cs [160:212]
internal static IServiceCollection AddServicesForFunctionTarget(IServiceCollection services, Type functionType)
{
// Make sure we can determine the actual function type later on.
services.AddSingleton(new FunctionTypeProvider(functionType));
if (typeof(IHttpFunction).IsAssignableFrom(functionType))
{
services.AddScoped(typeof(IHttpFunction), functionType);
}
else if (typeof(ICloudEventFunction).IsAssignableFrom(functionType))
{
services
.AddScoped<IHttpFunction, CloudEventAdapter>()
.AddSingleton<CloudEventFormatter>(new JsonEventFormatter())
.AddScoped(typeof(ICloudEventFunction), functionType);
}
else if (GetGenericInterfaceImplementationTypeArguments(functionType, typeof(ITypedFunction<,>)) is Type[] signatureTypes)
{
Type requestType = signatureTypes[0];
Type responseType = signatureTypes[1];
services
.AddScoped(typeof(IHttpFunction), typeof(TypedFunctionAdapter<,>).MakeGenericType(signatureTypes))
.AddScoped(typeof(ITypedFunction<,>).MakeGenericType(signatureTypes), functionType);
// Provide JSON reader/writer implementations using System.Text.Json by default.
// If the user provides a reader (or writer) in the startup class, that will take priority.
Type jsonReaderType = typeof(JsonHttpRequestReader<>).MakeGenericType(requestType);
Type jsonWriterType = typeof(JsonHttpResponseWriter<>).MakeGenericType(responseType);
services.AddSingleton(typeof(IHttpRequestReader<>).MakeGenericType(requestType), jsonReaderType);
services.AddSingleton(typeof(IHttpResponseWriter<>).MakeGenericType(responseType), jsonWriterType);
}
else if (GetGenericInterfaceImplementationTypeArgument(functionType, typeof(ICloudEventFunction<>)) is Type payloadType)
{
services
.AddScoped(typeof(IHttpFunction), typeof(CloudEventAdapter<>).MakeGenericType(payloadType))
.AddScoped(typeof(ICloudEventFunction<>).MakeGenericType(payloadType), functionType);
var formatter = CloudEventFormatterAttribute.CreateFormatter(payloadType);
// Only add the formatter here if we have one. Even if we have one, it can be overridden by a function
// startup class adding its own. If no formatter is available, CloudEventAdapter<TData> will fail
// with a helpful error message in the constructor.
if (formatter is not null)
{
services.AddSingleton(formatter);
}
}
else
{
throw new InvalidOperationException($"Function type '{functionType.FullName}' doesn't support any known function interfaces.");
}
return services;
}