Matthew Layton
Matthew Layton

Reputation: 42260

Instantiating objects with .NET Core's DI container

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

Answers (3)

David Ali
David Ali

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

kiripk
kiripk

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).

See: https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance

Upvotes: 21

Matthew Layton
Matthew Layton

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

Related Questions