Builder.cs: Dependency Configuration
I can’t take credit for this pattern but some co-workers of mine showed me this and I absolutely fell in love with this pattern. Instead of creating an extensions folder and adding all of the configuration classes and methods.. Why not just create a single class called Builder.cs and put it in the root? I started trying this out on projects and I now find it to be a very good way of organizing dependency injection and configuration. It’s a common pattern that can easily be used across multiple projects.
Builder.cs
namespace Microsoft.Extensions.DependencyInjection;
public static class Builder
{
public static IServiceCollection AddApplicationConfiguration(this IServiceCollection services, IConfiguration configuration)
{
// factories
services.AddTransient<ISmsFactory, SmsFactoryService>();
// inject: sms
services.AddTransient<ITwilioService, TwilioService>();
// inject: factories
services.AddTransient<IEmailFactory, EmailFactoryService>();
services.AddTransient<ISmsFactory, SmsFactoryService>();
return services;
}
}
Making Builder Methods Extensible Using Actions
This is a very useful trick especially if we’re developing NuGet packages that are being reshared and may need standard configuration with the ability to override.
Here’s a configuration extension for MassTransit that allows overriding default values.
public static IServiceCollection ConfigureMassTransit(this IServiceCollection services, MassTransitConfiguration masstransitConfig,
Action<IServiceCollectionBusConfigurator> actionMasstransit = null,
Action<IBusRegistrationContext, IServiceBusBusFactoryConfigurator> serviceBusAction = null,
Action<IBusRegistrationContext, IRabbitMqBusFactoryConfigurator> rabbitMqAction = null,
Action<IBusRegistrationContext, IAmazonSqsBusFactoryConfigurator> amazonSqsAction = null)
{
services.AddMassTransit(x =>
{
if (masstransitConfig.Service == MassTransitServiceType.AzureServiceBus)
{
actionMasstransit?.Invoke(x);
x.UsingAzureServiceBus((context, cfg) =>
{
cfg.Host(masstransitConfig.AzureServiceBus.ConnectionString);
serviceBusAction?.Invoke(context, cfg);
});
}
else if (masstransitConfig.Service == MassTransitServiceType.RabbitMq)
{
actionMasstransit?.Invoke(x);
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(masstransitConfig.RabbitMq.Host, masstransitConfig.RabbitMq.VirtualHost, h =>
{
h.Username(masstransitConfig.RabbitMq.Username);
h.Password(masstransitConfig.RabbitMq.Password);
});
rabbitMqAction?.Invoke(context, cfg);
});
}
else if (masstransitConfig.Service == MassTransitServiceType.AmazonSqs)
{
actionMasstransit?.Invoke(x);
x.UsingAmazonSqs((context, cfg) =>
{
cfg.Host(masstransitConfig.AmazonSqs.Host, h =>
{
h.AccessKey(masstransitConfig.AmazonSqs.AccessKey);
h.SecretKey(masstransitConfig.AmazonSqs.SecretKey);
// specify a scope for all queues
h.Scope(masstransitConfig.AmazonSqs.Scope);
// scope top ics as well
h.EnableScopedTopics();
});
amazonSqsAction?.Invoke(context, cfg);
});
}
});
return services;
}













