- Published on
Extending Dependency Injection in .NET
- Authors
- Name
- Jeevan Wijerathna
- @iamjeevanvj
Extending Dependency Injection in .NET
In .NET, the built-in Dependency Injection (DI) system is powerful and flexible, but sometimes you need to extend or customize it for advanced scenarios. Here are several options and techniques to extend DI in .NET:
1. Custom Service Providers
You can implement your own
IServiceProvider
Example: Using Autofac
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureContainer<ContainerBuilder>(builder => { builder.RegisterType<MyService>().As<IMyService>(); });
2. ServiceProvider Extensions
You can write extension methods for
IServiceCollection
Example:
public static class MyServiceCollectionExtensions { public static IServiceCollection AddMyFeature(this IServiceCollection services) { services.AddScoped<IMyService, MyService>(); services.AddSingleton<IMyHelper, MyHelper>(); return services; } }
Now you can call
services.AddMyFeature();
3. Factory and Delegates
For services that require runtime parameters or complex construction, you can use factories or delegate registrations.
Example:
services.AddTransient<IMyService>(provider => { var config = provider.GetRequiredService<IConfiguration>(); return new MyService(config["SomeSetting"]); });
4. Decorator Pattern
You can use DI to implement the decorator pattern, wrapping services with additional behavior (like logging, caching, etc.).
Example:
services.AddScoped<IMyService, MyService>(); services.Decorate<IMyService, MyServiceLoggingDecorator>();
(Note: The
Decorate
5. Conditional Registration
You can register services conditionally based on environment, configuration, or other logic.
Example:
if (env.IsDevelopment()) services.AddSingleton<IMyService, DevMyService>(); else services.AddSingleton<IMyService, ProdMyService>();
6. Open Generics
You can register open generic types, allowing DI to resolve generic services.
Example:
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
7. Modules and Assemblies Scanning
Some containers (like Autofac) support scanning assemblies and registering services automatically based on conventions or attributes.
Example with Autofac:
builder.RegisterAssemblyTypes(typeof(Startup).Assembly) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces();
8. Integration with Other Frameworks
You can integrate DI with frameworks like MediatR, ASP.NET Core MVC, SignalR, and more, often using extension methods or packages that register handlers, controllers, or hubs automatically.
9. Options Pattern and Configuration Binding
You can bind configuration sections to strongly-typed options classes and inject them.
Example:
services.Configure<MyOptions>(configuration.GetSection("MyOptions"));
10. Service Location (Advanced/Discouraged)
You can inject
IServiceProvider
Summary
You can extend DI in .NET by using third-party containers, writing extension methods, using factories and decorators, registering open generics, scanning assemblies, and integrating with other frameworks. The built-in system is flexible, but these techniques allow you to handle even the most complex dependency scenarios in large applications.