VDT.Core.DependencyInjection
3.2.0
See the version list below for details.
dotnet add package VDT.Core.DependencyInjection --version 3.2.0
NuGet\Install-Package VDT.Core.DependencyInjection -Version 3.2.0
<PackageReference Include="VDT.Core.DependencyInjection" Version="3.2.0" />
<PackageVersion Include="VDT.Core.DependencyInjection" Version="3.2.0" />
<PackageReference Include="VDT.Core.DependencyInjection" />
paket add VDT.Core.DependencyInjection --version 3.2.0
#r "nuget: VDT.Core.DependencyInjection, 3.2.0"
#:package VDT.Core.DependencyInjection@3.2.0
#addin nuget:?package=VDT.Core.DependencyInjection&version=3.2.0
#tool nuget:?package=VDT.Core.DependencyInjection&version=3.2.0
VDT.Core.DependencyInjection
Provides extensions for Microsoft.Extensions.DependencyInjection.IServiceCollection
Features
- Flexible service registration
- Convention-based service registration
- Attribute-based service registration
- Decorator pattern implementation
Flexible service registration
The extension method ServiceCollectionExtensions.AddServices is used to register all services provided by a ServiceRegistrationOptions object built with
the provided setup action. The ServiceRegistrationOptions class provides methods to build it in a fluent way:
AddAssemblyadds an assembly to scan for servicesAddAssembliesadds multiple assemblies to scan for services- Overloads are provided to add multiple assemblies as a parameter array or enumerable
- Overloads are provided to search for assemblies recursively by predicate or assembly name prefix
AddServiceTypeProvideradds a method that returns service types for a given implementation type found in the assemblies- These methods must match the delegate method
ServiceTypeProvider - It is possible to supply a
ServiceLifetimeProviderthat returns the appropriateServiceLifetimefor a given service type and implementation type
- These methods must match the delegate method
UseDefaultServiceLifetimesets the defaultServiceLifetimeto use if noServiceLifetimeProviderwas provided or it did not return aServiceLifetimeUseServiceRegistrarsets the method to use for registering services- This method must match the delegate method
ServiceRegistrar - By default a new
ServiceDescriptorwill be created with the found service type, implementation type and lifetime
- This method must match the delegate method
Example
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddServices(setupAction: options => options
// Add assemblies to scan
.AddAssembly(assembly: typeof(Startup).Assembly)
.AddAssemblies(typeof(MyService).Assembly, typeof(MyOtherService).Assembly)
// Add all project assemblies based on prefix
.AddAssemblies(entryAssembly: typeof(Startup).Assembly, assemblyPrefix: "MyCompany.MySolution")
// Add a service type provider with a lifetime provider
.AddServiceTypeProvider(
serviceTypeProvider: implementationType => implementationType.GetInterfaces().Where(serviceType => serviceType.Assembly == implementationType.Assembly),
serviceLifetimeProvider: (serviceType, implementationType) => ServiceLifetime.Scoped
)
// Add a service type provider without a lifetime provider
.AddServiceTypeProvider(
serviceTypeProvider: implementationType => implementationType.GetInterfaces().Where(serviceType => serviceType.Assembly == implementationType.Assembly)
)
// Optional: use a different ServiceLifetime than Scoped by default
.UseDefaultServiceLifetime(serviceLifetime: ServiceLifetime.Transient)
// Optional: provide your own method for registering services
.UseServiceRegistrar(
serviceRegistrar: (services, serviceType, implementationType, serviceLifetime) => services.Add(new ServiceDescriptor(serviceType, implementationType, serviceLifetime))
)
);
// ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
// ...
}
}
Convention-based service registration
The class DefaultServiceTypeProviders contains three ways to register services based on common conventions:
SingleInterfacereturns the single interface if an implementation type implements exactly one interfaceInterfaceByNamereturns interface types found on on implementation types that follow the .NET naming guideline of naming class-interface pairs:- Service interface name
IMyService - Implementation class name
MyService
- Service interface name
CreateGenericInterfaceTypeProvidergenerates aServiceTypeProviderthat finds generic types based on a generic type definition- This is useful if you implement generic interface types such request handlers, command handlers or query handlers
Example
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddServices(setupAction: options => options
// Add assemblies to scan
.AddAssembly(assembly: typeof(Startup).Assembly)
.AddAssembly(assembly: typeof(MyService).Assembly)
// Add default service type providers
.AddServiceTypeProvider(
serviceTypeProvider: DefaultServiceTypeProviders.SingleInterface
)
.AddServiceTypeProvider(
serviceTypeProvider: DefaultServiceTypeProviders.InterfaceByName
)
.AddServiceTypeProvider(
serviceTypeProvider: DefaultServiceTypeProviders.CreateGenericInterfaceTypeProvider(typeof(IRequestHandler))
)
);
// ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
// ...
}
}
Attribute-based service registration
The extension method Attributes.ServiceRegistrationOptionsExtensions.AddAttributeServiceTypeProviders allows you to move registration for your services from
the Startup class to the services themselves without using convention-based registration. Simply mark your services or service implementations with the
different types of service attributes to indicate that a service should be registered and use the options extension to add the correct providers.
There are six attributes available:
Attributes.TransientServiceAttributemarks a service to be registered as a transient service with the supplied implementation typeAttributes.ScopedServiceAttributemarks a service to be registered as a scoped service with the supplied implementation typeAttributes.SingletoncopedServiceAttributemarks a service to be registered as a singleton service with the supplied implementation typeAttributes.TransientServiceImplementationAttributemarks the implementation to be registered as a transient service under the supplied service typeAttributes.ScopedServiceImplementationAttributemarks the implementation to be registered as a scoped service under the supplied service typeAttributes.SingletonServiceImplementationAttributemarks the implementation to be registered as a singleton service under the supplied service type
The extension methods Attributes.ServiceCollectionExtensions.AddAttributeServices are convenience methods that you can use if you don't need any other
service type providers or additional setup of service registration.
Example
// Mark the service to be registered
[ScopedService(implementationType: typeof(Bar))]
public interface IBar {
void Foo();
}
public class Bar {
public void Foo() {
// ...
}
}
public interface IBar {
void Foo();
}
// Mark the implementation
[ScopedServiceImplementation(serviceType: typeof(Bar))]
public class Bar {
public void Foo() {
// ...
}
}
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// Register using options
services.AddServices(setupAction: options => options
.AddAssembly(assembly: typeof(Startup).Assembly)
.AddAttributeServiceTypeProviders()
);
// Register using convenience method
services.AddAttributeServices(assembly: typeof(Startup).Assembly);
// Register using convenience method and apply decorators
services.AddAttributeServices(assembly: typeof(Startup).Assembly, decoratorSetupAction: options => options.AddAttributeDecorators());
// ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
// ...
}
}
Decorators
The extension methods Decorators.ServiceCollectionExtensions.AddTransient, Decorators.ServiceCollectionExtensions.AddScoped and
Decorators.ServiceCollectionExtensions.AddSingleton with an Action<Decorators.DecoratorOptions> parameter allow you to register services decorated with
your own implementations of the Decorators.IDecorator interface.
If you wish to use decorators when using options-based service registration as described above, it is possible to use the
Decorators.ServiceRegistrationOptionsExtensions.UseDecoratorServiceRegistrar extension method which can apply decorator options to all classes that are
registered using the provided ServiceTypeProvider implementations.
The Decorators.IDecorator interface has three methods:
BeforeExecuteallows you to execute code before execution of the decorated methodAfterExecuteallows you to execute code after execution of the decorated methodOnErrorallows you to execute code if the decorated method throws an error
There are two ways to apply decorators to your services: you can apply a custom attribute to the methods on either the service or service imlementation you want decorated, or you can provide predicates with decorator types when registering the services.
Example
public class LogDecorator : IDecorator {
public void BeforeExecute(MethodExecutionContext context) {
Debug.WriteLine($"Executing '{context.TargetType.FullName}.{context.Method.Name}'");
}
public void AfterExecute(MethodExecutionContext context) {
Debug.WriteLine($"Executed '{context.TargetType.FullName}.{context.Method.Name}'");
}
public void OnError(MethodExecutionContext context, System.Exception exception) {
Debug.WriteLine($"Failed to execute '{context.TargetType.FullName}.{context.Method.Name}': {exception.Message}");
}
}
// For attribute based decoration
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute, IDecorateAttribute<LogDecorator> {
}
public interface IExample {
// Decorate from service
[Log]
void Foo();
void Bar();
}
public class Example : IExample {
public void Foo() {
// ...
}
// Decorate from implementation
[Log]
public void Bar() {
// ...
}
}
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// Register services with a provided decorator
services.AddServices(options => options
.AddAssembly(assembly: typeof(Startup).Assembly)
.AddServiceTypeProvider(
serviceTypeProvider: DefaultServiceTypeProviders.InterfaceByName
)
.UseDecoratorServiceRegistrar(setupAction: options => options.AddDecorator<LogDecorator>(predicate: method => method.Name == "Foo")
);
// Register services using attributes
services.AddServices(options => options
.AddAssembly(assembly: typeof(Startup).Assembly)
.AddServiceTypeProvider(
serviceTypeProvider: DefaultServiceTypeProviders.InterfaceByName
)
.UseDecoratorServiceRegistrar(setupAction: options => options.AddAttributeDecorators())
);
// Register a single service with a provided decorator
services.AddScoped<IExample, Example>(setupAction: options => options.AddDecorator<LogDecorator>(predicate: method => method.Name == "Foo");
// Register a single service using attributes
services.AddScoped<IExample, Example>(setupAction: options => options.AddAttributeDecorators());
// ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
// ...
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Castle.Core (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection (>= 6.0.0)
-
net6.0
- Castle.Core (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection (>= 6.0.0)
-
net7.0
- Castle.Core (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.0.0 | 192 | 2/12/2025 |
| 6.0.0 | 239 | 3/16/2024 |
| 5.0.0 | 279 | 11/24/2023 |
| 4.1.0 | 277 | 6/14/2023 |
| 4.0.0 | 292 | 6/11/2023 |
| 3.2.0 | 299 | 6/5/2023 |
| 3.1.0 | 299 | 5/28/2023 |
| 3.0.0 | 282 | 5/25/2023 |
| 2.1.2 | 284 | 5/22/2023 |
| 2.1.1 | 3,427 | 2/20/2022 |
| 2.1.0 | 611 | 2/12/2022 |
| 2.0.0 | 599 | 2/6/2022 |
| 1.3.0 | 496 | 11/27/2021 |
| 1.2.0 | 762 | 4/13/2021 |
| 1.1.0 | 559 | 3/16/2021 |
- Added Add extension methods for decorators with a lifetime parameter
- Refactored internals for simplicity and performance