Understanding IServiceCollection and IServiceProvider in ASP.NET Core: A Complete Guide to Dependency Injection
What is IServiceCollection?
IServiceCollection is a fundamental part of the Dependency Injection (DI) system in ASP.NET Core and .NET Core. It is used to register and configure the services that the application will need during runtime. By registering services with IServiceCollection, developers can promote loose coupling between components and enhance maintainability and testability.
Key Features of IServiceCollection:
Example :
services.AddTransient<IMyService, MyService>();
services.AddScoped<IRepository, Repository>();
services.AddSingleton<ILogger, Logger>();
2.Configuration and Options: You can also register configurations or settings using IServiceCollection to bind them to configuration sections.
services.Configure<MyAppSettings>(configuration.GetSection("MyAppSettings"));
3.Custom Services: Custom services can be registered by specifying how they should be created.
services.AddSingleton<ICustomService>(sp => new CustomService(Configuration["ConnectionString"]));
4.Dependency Resolution: Once services are registered, they can be resolved and injected into other classes or controllers.
public class MyController
{
private readonly IMyService _myService;
public MyController(IMyService myService)
{
_myService = myService;
}
}
How IServiceCollection Works:
IServiceCollectionis an interface representing a container that holds all the registered services in an ASP.NET Core application. It’s essentially a collection of ServiceDescriptorobjects. This interface is used to configure the DI system by adding services to the container during the Program.cs phase of an application.
In the Program.cs file, you typically register services using the ConfigureServices method by calling methods like AddScoped, AddSingleton, and AddTransient. These methods internally create ServiceDescriptorobjects and add them to the IServiceCollection.
public void ConfigureServices(IServiceCollection services)
{
// Register a service with a Scoped lifetime
services.AddScoped<IMyService, MyService>();
}
When you call services.AddScoped(), it essentially adds a new ServiceDescriptorto the IServiceCollection.
What is ServiceDescriptor in ASP.NET Core?
In ASP.NET Core, ServiceDescriptor defines how services are managed in the Dependency Injection (DI) system. It holds information about:
How ServiceDescriptor Works
A ServiceDescriptor tells ASP.NET Core how to create and manage a service. There are three main ways to create a ServiceDescriptor:
For example:
var descriptor = new ServiceDescriptor(
typeof(IMyService), // Service Type
typeof(MyService), // Implementation Type
ServiceLifetime.Scoped // Lifetime (Scoped, Singleton, or Transient)
);
Relationship Between ServiceDescriptor and IServiceCollection
IServiceCollection is like a container that holds all the services. When you use methods like AddScoped or AddSingleton, ASP.NET Core creates a ServiceDescriptor for each service and adds it to IServiceCollection.
For example:
services.AddScoped<IMyService, MyService>();
This creates a ServiceDescriptor that registers IMyService with MyService as its implementation, and specifies a Scoped lifetime (meaning one instance per request).
Manually Creating ServiceDescriptor
Instead of using methods like AddScoped, you can manually create and add a ServiceDescriptor:
var descriptor = new ServiceDescriptor(
typeof(IMyService),
typeof(MyService),
ServiceLifetime.Scoped
);
services.Add(descriptor);
Key Properties of ServiceDescriptor
The ServiceDescriptor class includes the following key properties that define how services are managed:
Here is a simplified structure of the ServiceDescriptor class:
领英推荐
public class ServiceDescriptor
{
public Type ServiceType { get; }
public Type ImplementationType { get; }
public object ImplementationInstance { get; }
public Func<IServiceProvider, object> ImplementationFactory { get; }
public ServiceLifetime Lifetime { get; }
}
Summary of what was said:
1.IServiceCollection is the container used to register all services in an application.
2.ServiceDescriptor acts as the blueprint that defines how each service should be created and managed, specifying the type, implementation, and lifetime (Transient, Scoped, or Singleton).
3.Methods like AddScoped, AddSingleton, and AddTransient in IServiceCollection automatically create and register ServiceDescriptor instances. These methods help configure Dependency Injection (DI) in ASP.NET Core.
What is IServiceProvider?
IServiceProvider is a core part of the Dependency Injection (DI) system in ASP.NET Core. It is responsible for resolving instances of services at runtime, allowing these services to be injected into other classes, like controllers or services, as needed. It also ensures that services adhere to their expected lifetime (e.g., Singleton, Scoped, or Transient).
After all the services are registered using IServiceCollection, the next step is to create an IServiceProvider. This is done using the BuildServiceProvider() method, which wraps the service registrations and enables the application to resolve services when required.
In short:
Here’s how you can create and use an IServiceProvider:
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ClassA>();
serviceCollection.AddSingleton<IThing, ClassB>();
var serviceProvider = serviceCollection.BuildServiceProvider();
How Does BuildServiceProvider() Work?
The BuildServiceProvider() method compiles the list of services registered in IServiceCollection and generates an IServiceProvider. This method takes care of the internal mechanics of service resolution.
Here’s an example of how to resolve a service:
var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetService<IMyService>(); // Resolving the registered service
Workflow of IServiceProvider
Full Example of Service Registration and Resolution:
public void ConfigureServices(IServiceCollection services)
{
// Registering services in IServiceCollection
services.AddScoped<IMyService, MyService>();
}
// Later in the application lifecycle
var serviceProvider = services.BuildServiceProvider();
// Using IServiceProvider to resolve services
var myService = serviceProvider.GetService<IMyService>();
In this example:
Conclusion
In ASP.NET Core, Dependency Injection (DI) is vital for creating loosely coupled, testable, and maintainable applications. The IServiceCollection and IServiceProvider interfaces work together to manage service registration and resolution.
IServiceCollection is used at startup to register services with methods like AddTransient(), AddScoped(), and AddSingleton(), defining their lifetimes:
This decouples dependencies, reduces code duplication, and promotes modularity, allowing components to focus on their specific responsibilities.
During runtime, IServiceProvider resolves dependencies as needed. It uses the configuration from IServiceCollection to provide instances, improving efficiency through:
Benefits of Using IServiceCollection and IServiceProvider
In summary, IServiceCollection and IServiceProvider enable a structured approach to dependency management, allowing developers to focus on business logic, resulting in cleaner, maintainable, and robust applications.
Feature Comparison
Junior Back End Developer @Dotin C# | Asp .NET Core | React | Creator
2 个月Very helpful
Junior Asp .Net Developer
2 个月Interesting