我如何手动解析一个类型使用ASP。NET核心MVC内置依赖注入框架?

设置容器非常简单:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddTransient<ISomeService, SomeConcreteService>();
}

但是如何在不执行注入的情况下解析ISomeService呢?例如,我想这样做:

ISomeService service = services.Resolve<ISomeService>();

在IServiceCollection中没有这样的方法。


当前回答

手动解析实例需要使用IServiceProvider接口:

在启动时解决依赖关系。ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>();

    var serviceProvider = services.BuildServiceProvider();
    var service = serviceProvider.GetService<IMyService>();
}

解决启动中的依赖关系。配置

public void Configure(
    IApplicationBuilder application,
    IServiceProvider serviceProvider)
{
    // By type.
    var service1 = (MyService)serviceProvider.GetService(typeof(MyService));

    // Using extension method.
    var service2 = serviceProvider.GetService<MyService>();

    // ...
}

解决启动中的依赖关系。在ASP中配置。NET Core 3

public void Configure(
    IApplicationBuilder application,
    IWebHostEnvironment webHostEnvironment)
{
    application.ApplicationServices.GetService<MyService>();
}

使用运行时注入的服务

有些类型可以作为方法参数注入:

public class Startup
{
    public Startup(
        IHostingEnvironment hostingEnvironment,
        ILoggerFactory loggerFactory)
    {
    }

    public void ConfigureServices(
        IServiceCollection services)
    {
    }

    public void Configure(
        IApplicationBuilder application,
        IHostingEnvironment hostingEnvironment,
        IServiceProvider serviceProvider,
        ILoggerFactory loggerfactory,
        IApplicationLifetime applicationLifetime)
    {
    }
}

解决控制器动作中的依赖关系

[HttpGet("/some-action")]
public string SomeAction([FromServices] IMyService myService) => "Hello";

其他回答

如果你用模板生成一个应用程序,你会在Startup类上有这样的东西:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddMvc();
}

然后你可以在那里添加依赖项,例如:

services.AddTransient<ITestService, TestService>();

如果你想在你的控制器上访问ITestService,你可以在构造函数上添加IServiceProvider,它将被注入:

public HomeController(IServiceProvider serviceProvider)

然后你可以解析你添加的服务:

var service = serviceProvider.GetService<ITestService>();

注意,要使用通用版本,你必须包含扩展名的命名空间:

using Microsoft.Extensions.DependencyInjection;

ITestService.cs

public interface ITestService
{
    int GenerateRandom();
}

TestService.cs

public class TestService : ITestService
{
    public int GenerateRandom()
    {
        return 4;
    }
}

Startup.cs (ConfigureServices)

public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddMvc();

    services.AddTransient<ITestService, TestService>();
}

HomeController.cs

using Microsoft.Extensions.DependencyInjection;

namespace Core.Controllers
{
    public class HomeController : Controller
    {
        public HomeController(IServiceProvider serviceProvider)
        {
            var service = serviceProvider.GetService<ITestService>();
            int rnd = service.GenerateRandom();
        }
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddDbContext<ConfigurationRepository>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString")));

    services.AddScoped<IConfigurationBL, ConfigurationBL>();
    services.AddScoped<IConfigurationRepository, ConfigurationRepository>();
}

您可以通过这种方式在诸如AuthorizeAttribute之类的属性中注入依赖项

var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService));

手动解析实例需要使用IServiceProvider接口:

在启动时解决依赖关系。ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>();

    var serviceProvider = services.BuildServiceProvider();
    var service = serviceProvider.GetService<IMyService>();
}

解决启动中的依赖关系。配置

public void Configure(
    IApplicationBuilder application,
    IServiceProvider serviceProvider)
{
    // By type.
    var service1 = (MyService)serviceProvider.GetService(typeof(MyService));

    // Using extension method.
    var service2 = serviceProvider.GetService<MyService>();

    // ...
}

解决启动中的依赖关系。在ASP中配置。NET Core 3

public void Configure(
    IApplicationBuilder application,
    IWebHostEnvironment webHostEnvironment)
{
    application.ApplicationServices.GetService<MyService>();
}

使用运行时注入的服务

有些类型可以作为方法参数注入:

public class Startup
{
    public Startup(
        IHostingEnvironment hostingEnvironment,
        ILoggerFactory loggerFactory)
    {
    }

    public void ConfigureServices(
        IServiceCollection services)
    {
    }

    public void Configure(
        IApplicationBuilder application,
        IHostingEnvironment hostingEnvironment,
        IServiceProvider serviceProvider,
        ILoggerFactory loggerfactory,
        IApplicationLifetime applicationLifetime)
    {
    }
}

解决控制器动作中的依赖关系

[HttpGet("/some-action")]
public string SomeAction([FromServices] IMyService myService) => "Hello";
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ISelfServiceConfigLoad, SelfServiceConfigLoader>();
    var sp = services.BuildServiceProvider();
    var configservice = sp.GetServices<ISelfServiceConfigLoad>();
    services.AddSingleton<IExtractor, ConfigExtractor>( sp =>
    {
        var con = sp.GetRequiredService<ISelfServiceConfigLoad>();
        var config = con.Load();
        return new ConfigExtractor(config.Result);
    });
    services.AddSingleton<IProcessor<EventMessage>, SelfServiceProcessor>();          
    services.AddTransient<ISolrPush, SolrDataPush>();
    services.AddSingleton<IAPICaller<string, string>, ApiRestCaller<string, string>>();
    services.AddSingleton<IDataRetriever<SelfServiceApiRequest, IDictionary<string, object>>, SelfServiceDataRetriever>();
}