Edward
Edward

Reputation: 29976

Who and How initialize the Interface in Dependence Injection

For Asp.Net Core Dependence Injection, I know we register the dependence into IServiceCollection, and use IServiceProvider to get the instance.

I am wondering the code which register and initialize the IServiceCollection.

For Interface Injection, why did it know get the instance from the ServiceCollection? Which code implement this feature?

I want to know the global controller who and how control this?

Upvotes: 2

Views: 5240

Answers (3)

Jesús López
Jesús López

Reputation: 9221

This is how I do it on .net core 2.2:

using System;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleAppDependencyInjection
{
    class Program
    {
        static void Main(string[] args)
        {
            var serviceProvider = ConfigureContainer();
            var service1 = serviceProvider.GetService<Service1>();
            var service2 = serviceProvider.GetService<Service2>();

            Debug.Assert(service1 != null);
            Debug.Assert(service2 != null);
        }

        static IServiceProvider ConfigureContainer()
        {
            var services = new ServiceCollection();
            ConfigureServices(services);
            return services.BuildServiceProvider();
        }

        static void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<Service1>();
            services.AddSingleton<Service2>();
        }
    }

    public class Service1
    {
        public Service1()
        {
        }
    }

    public class Service2
    {
        Service1 service1;
        public Service2(Service1 service1)
        {
            this.service1 = service1;
        }
    }
}

Upvotes: 0

Nkosi
Nkosi

Reputation: 247088

To supplement already provided answer, outside of asp.net-core, the DI framework can be used on its own, separately, as it is a completely decoupled module.

Essential .NET - Dependency Injection with .NET Core

public static void Main() {
    IServiceCollection serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);
    var application = new MyApplication(serviceCollection);

    // Run
    // ...
}

static private void ConfigureServices(IServiceCollection services) {
    ILoggerFactory loggerFactory = new Logging.LoggerFactory();
    services.AddInstance<ILoggerFactory>(loggerFactory);

    //...
}

The only difference is that now you have to create the collection on your own instead of the framework doing it for you as part of its pipeline.

From comments,

It bears mentioning that an ASP.NET Core app is nothing but a console app, which therefore explains why you can use IServiceColleciton in a basic console app as well, or anywhere else you like, for that matter.

Upvotes: 1

CodeFuller
CodeFuller

Reputation: 31282

When you create ASP.NET Core project, the following code is generated for Program.Main():

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

The instance of IServiceCollection is created inside WebHost.CreateDefaultBuilder(args) and then is passed to Startup.ConfigureServices(IServiceCollection services) call.

If you want to track the calls chain in ASP.NET Core source code, here it is (links to source code on github included):

WebHost.CreateDefaultBuilder() calls WebHostBuilderExtensions.UseDefaultServiceProvider() extension method:

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder()

        .UseIISIntegration()
        // ...
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        });

        // ...

    return builder;
}

WebHostBuilderExtensions.UseDefaultServiceProvider() calls WebHostBuilder.ConfigureServices() method:

public static IWebHostBuilder UseDefaultServiceProvider(this IWebHostBuilder hostBuilder, Action<WebHostBuilderContext, ServiceProviderOptions> configure)
{
    return hostBuilder.ConfigureServices((context, services) =>
    {
        var options = new ServiceProviderOptions();
        configure(context, options);
        services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(new DefaultServiceProviderFactory(options)));
    });
}

WebHostBuilder eventually creates the instance of ServiceCollection and calls Startup.ConfigureServices() method (through stored action):

private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
{
    //  ...

    // Creation of `ServiceCollection` instance
    var services = new ServiceCollection();

    //  ...

    foreach (var configureServices in _configureServicesDelegates)
    {
        configureServices(_context, services);
    }

    //  ...
}

Upvotes: 4

Related Questions