Is there a way to get IServiceProvider.GetService<T>
to return an instance even if T
is not explicitly registered with the container?
If I know that T
has dependencies I'd like them to be injected based on their registrations without having to register T
itself.
I believe Ninject will intelligently work out the most appropriate constructor or fallback to a parameterless constructor if no suitable constructor is found. I'd like to replicate this behaviour using the standard MVC Core DI framework if possible.
Resolve dependencies using IServiceProvider You can use the IServiceCollection interface to create a dependency injection container. Once the container has been created, the IServiceCollection instance is composed into an IServiceProvider instance. You can use this instance to resolve services.
Framework level dependency injection is powerful feature of . NET Core. It is easy to configure and easy to use through constructor injection. We used dependency injection with view component to display top menu and to correctly highlight current top level category.
Dependency injection (also known as DI) is a design pattern in which a class or object has its dependent classes injected (passed to it by another class or object) rather than create them directly. Dependency injection facilitates loose coupling and promotes testability and maintenance.
When you make it explicit, you've got basically two options: 1. Configure the DI to return transient objects and dispose these objects yourself. 2. Configure a factory and instruct the factory to create new instances.
To keep this up to date: There is a way to achieve exactly what you are looking for.
Standard dependency injector of .NET Core
In my sample i create a new instance of IServiceCollection for showcase:
var services = new ServiceCollection(); var serviceProvider = services.BuildServiceProvider(); var unregisteredClassInstance = ActivatorUtilities.CreateInstance<UnregisteredClass>(serviceProvider);
This gives you an instance of the type UnregisteredClass which was not previously registered, but takes constructor parameters which are registered previously on the ServiceCollection.
Third party dependency injectors
SimpleInjector can do that easily with container.GetInstance<UnregisteredClass>();
.
While there is no way provided by default to resolve un-registered concrete types you can add an extension function that will give you the ability. Its important to note that this can be abused as a service locator which is an Anti-pattern. Depending on your usage its possible to take advantage of this without turning it into a service locator.
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace Microsoft.Extensions.DependencyInjection { public static class ServiceProviderExtensions { public static TService AsSelf<TService>(this IServiceProvider serviceProvider) { return (TService)AsSelf(serviceProvider, typeof(TService)); } public static object AsSelf(this IServiceProvider serviceProvider, Type serviceType) { var constructors = serviceType.GetConstructors(BindingFlags.Public | BindingFlags.Instance) .Select(o => o.GetParameters()) .ToArray() .OrderByDescending(o => o.Length) .ToArray(); if (!constructors.Any()) { return null; } object[] arguments = ResolveParameters(serviceProvider, constructors); if (arguments == null) { return null; } return Activator.CreateInstance(serviceType, arguments); } private static object[] ResolveParameters(IServiceProvider resolver, ParameterInfo[][] constructors) { foreach (ParameterInfo[] constructor in constructors) { bool hasNull = false; object[] values = new object[constructor.Length]; for (int i = 0; i < constructor.Length; i++) { var value = resolver.GetService(constructor[i].ParameterType); values[i] = value; if (value == null) { hasNull = true; break; } } if (!hasNull) { // found a constructor we can create. return values; } } return null; } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With