Reputation: 42260
I'm using an IServiceCollection
to create a list of required services for my objects. Now I want to instantiate an object and have the DI container resolve the dependencies for that object
Example
// In my services config.
services
.AddTransient<IMyService, MyServiceImpl>();
// the object I want to create.
class SomeObject
{
public SomeObject(IMyService service)
{
...
}
}
How to I get the DI container to create an object of type SomeObject
, with the dependecies injected? (presumably this is what it does for controllers?)
Note: I do not want to store SomeObject
in the services collection, I just want to be able to do something like this...
SomeObject obj = startup.ServiceProvider.Resolve<SomeObject>();
... Rationale: I don't have to add all of my controllers to the service container, so I don't see why I would have to add SomeObject
to it either!?
Upvotes: 17
Views: 15528
Reputation: 11
Extension method:
public static class Extensions
{
public static T BuildObject<T>(this IServiceProvider serviceProvider, params object[] parameters)
=> ActivatorUtilities.CreateInstance<T>(serviceProvider, parameters);
}
Usage:
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var ss = HttpContext.RequestServices.BuildObject<SomeService>();
}
Upvotes: 1
Reputation: 276
As stated in the comments to the marked answer, you can use ActivatorUtilities.CreateInstance
method. This functionality already exists in .NET Core (since version 1.0, I believe).
Upvotes: 21
Reputation: 42260
It's a little rough, but this works
public static class ServiceProviderExtensions
{
public static TResult CreateInstance<TResult>(this IServiceProvider provider) where TResult : class
{
ConstructorInfo constructor = typeof(TResult).GetConstructors()[0];
if(constructor != null)
{
object[] args = constructor
.GetParameters()
.Select(o => o.ParameterType)
.Select(o => provider.GetService(o))
.ToArray();
return Activator.CreateInstance(typeof(TResult), args) as TResult;
}
return null;
}
}
Upvotes: 6