Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从ConfigureServices内使用ASP.NET Core DI解析实例_C#_Dependency Injection_Asp.net Core_Asp.net Core Mvc - Fatal编程技术网

C# 从ConfigureServices内使用ASP.NET Core DI解析实例

C# 从ConfigureServices内使用ASP.NET Core DI解析实例,c#,dependency-injection,asp.net-core,asp.net-core-mvc,C#,Dependency Injection,Asp.net Core,Asp.net Core Mvc,如何使用ASP.NET Core MVC内置的依赖项注入框架手动解析类型 设置容器非常简单: public void ConfigureServices(IServiceCollection services) { // ... services.AddTransient<ISomeService, SomeConcreteService>(); } IServiceCollection中没有此类方法手动解析实例涉及使用以下接口: 正在解析Startup.Conf

如何使用ASP.NET Core MVC内置的依赖项注入框架手动解析类型

设置容器非常简单:

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

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

IServiceCollection

中没有此类方法手动解析实例涉及使用以下接口:

正在解析Startup.ConfigureServices中的依赖项 解析控制器操作中的依赖项 该接口用于构建依赖项注入容器。在完全构建之后,它将被组合成一个实例,您可以使用它来解析服务。您可以将
IServiceProvider
注入任何类。
iaapplicationbuilder
HttpContext
类也可以通过各自的or属性提供服务提供者

IServiceProvider
定义解析服务的方法:

var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
还有几种方便的扩展方法可用,例如(为
Microsoft.Extensions.DependencyInjection
使用
添加

解析startup类内的服务 注入依赖项 运行时的宿主服务提供程序可以将某些服务注入
启动
类的构造函数中,例如, (
IHostingEnvironment
在3.0之前的版本中)和
iSeries提供程序
。请注意,后者是由宿主层构建的实例,仅包含启动应用程序的基本服务

ConfigureServices()
方法不允许注入服务,它只接受
IServiceCollection
参数。这很有意义,因为
ConfigureServices()
是注册应用程序所需服务的地方。但是,您可以在此处使用在启动的构造函数中注入的服务,例如:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    // Use Configuration here
}
services.AddTransient<ITestService, TestService>();
然后可以将在
ConfigureServices()
中注册的任何服务注入
Configure()
方法;您可以在
iaapplicationbuilder
参数之后添加任意数量的服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IFooService>();
}

public void Configure(IApplicationBuilder app, IFooService fooService)
{
    fooService.Bar();
}
可以在
启动
类的构造函数中传递并直接使用
IServiceProvider
,但如上所述,它将包含有限的服务子集,因此效用有限:

public Startup(IServiceProvider serviceProvider)
{
    var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
请注意: 通常,您应该避免在
ConfigureServices()
方法中解析服务,因为这实际上是您配置应用程序服务的地方。有时您只需要访问
IOptions
实例。您可以通过将
IConfiguration
实例中的值绑定到
MyOptions
的实例来实现这一点(这基本上就是选项框架所做的):

或者对
AddSingleton/AddScoped/AddTransient
使用重载:

// Works for AddScoped and AddTransient as well
services.AddSingleton<IBarService>(sp =>
{
    var fooService = sp.GetRequiredService<IFooService>();
    return new BarService(fooService);
}
//也适用于addScope和AddTransient
services.AddSingleton(sp=>
{
var fooService=sp.GetRequiredService();
返回新的BarService(fooService);
}

手动解析服务(又称服务定位器)是。虽然它有它的用例(对于框架和/或基础结构层),但您应该尽可能避免它。

如果您使用模板生成应用程序,则在
启动
类中会有类似的内容:

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

    services.AddMvc();
}
然后可以在此处添加依赖项,例如:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    // Use Configuration here
}
services.AddTransient<ITestService, TestService>();
然后,您可以解析您添加的服务:

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

ITestService.cs

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

public interface ITestService
{
    int GenerateRandom();
}
public class TestService : ITestService
{
    public int GenerateRandom()
    {
        return 4;
    }
}
Startup.cs(配置服务)

public void配置服务(IServiceCollection服务)
{
services.AddApplicationInsightsTelemetry(配置);
services.AddMvc();
services.AddTransient();
}
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();
        }
使用Microsoft.Extensions.DependencyInjection;
名称空间核心控制器
{
公共类HomeController:控制器
{
公共家庭控制器(IServiceProvider服务提供商)
{
var service=serviceProvider.GetService();
int rnd=service.generateradom();
}
公共void配置服务(IServiceCollection服务)
{
services.AddMvc();
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“SqlConnectionString”));
services.addScope();
services.addScope();
}

您可以通过这种方式在属性(如AuthorizeAttribute)中注入依赖项

var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService));
public void Configure(IApplicationBuilder app)
    {
        //---------- Your code
        
        using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var resultLogic = serviceScope.ServiceProvider.GetService<IResultLogic>();
            resultLogic.YourMethod();
        }           

        //---------- Your code
    }

如果您只需要解析一个依赖项,以便将其传递给正在注册的另一个依赖项的构造函数,那么您可以这样做

假设您有一个包含字符串和等距服务的服务

public class AnotherService : IAnotherService
{
    public AnotherService(ISomeService someService, string serviceUrl)
    {
        ...
    }
}
在Startup.cs中注册此文件时,需要执行以下操作:

ISomeService service = services.Resolve<ISomeService>();
services.AddScoped<IAnotherService>(ctx => 
      new AnotherService(ctx.GetService<ISomeService>(), "https://someservice.com/")
);
services.AddScoped(ctx=>
新建另一个服务(ctx.GetService(),”https://someservice.com/")
);

我知道这是一个老问题,但我很惊讶这里没有一个相当明显和令人厌恶的黑客

您可以利用定义自己的ctor函数的能力,在定义服务时从服务中获取必要的值……显然,这将在每次请求服务时运行,除非您在第一次构造ctor时明确删除/清除并重新添加此服务的定义

此方法的优点是不需要您在配置服务期间构建或使用服务树。您仍在定义如何配置服务

public void ConfigureServices(IServiceCollection services)
{
    //Prey this doesn't get GC'd or promote to a static class var
    string? somevalue = null;

    services.AddSingleton<IServiceINeedToUse, ServiceINeedToUse>(scope => {
         //create service you need
         var service = new ServiceINeedToUse(scope.GetService<IDependantService>())
         //get the values you need
         somevalue = somevalue ?? service.MyDirtyHack();
         //return the instance
         return service;
    });
    services.AddTransient<IOtherService, OtherService>(scope => {
         //Explicitly ensuring the ctor function above is called, and also showcasing why this is an anti-pattern.
         scope.GetService<IServiceINeedToUse>();
         //TODO: Clean up both the IServiceINeedToUse and IOtherService configuration here, then somehow rebuild the service tree.
         //Wow!
         return new OtherService(somevalue);
    });
}
public void配置服务(IServiceCollection服务)
{
//这不会得到GC'd或提升为静态类var
字符串?somevalue=null;
services.AddSingleton(范围=>{
//创建您需要的服务
var service=new ServiceINeedToUse(scope.GetService())
//获取所需的值
somevalue=somevalue??service.MyDirtyHack();
//归还仪器
public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddMvc();

    services.AddTransient<ITestService, TestService>();
}
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>();
}
var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService));
public class AnotherService : IAnotherService
{
    public AnotherService(ISomeService someService, string serviceUrl)
    {
        ...
    }
}
services.AddScoped<IAnotherService>(ctx => 
      new AnotherService(ctx.GetService<ISomeService>(), "https://someservice.com/")
);
public void ConfigureServices(IServiceCollection services)
{
    //Prey this doesn't get GC'd or promote to a static class var
    string? somevalue = null;

    services.AddSingleton<IServiceINeedToUse, ServiceINeedToUse>(scope => {
         //create service you need
         var service = new ServiceINeedToUse(scope.GetService<IDependantService>())
         //get the values you need
         somevalue = somevalue ?? service.MyDirtyHack();
         //return the instance
         return service;
    });
    services.AddTransient<IOtherService, OtherService>(scope => {
         //Explicitly ensuring the ctor function above is called, and also showcasing why this is an anti-pattern.
         scope.GetService<IServiceINeedToUse>();
         //TODO: Clean up both the IServiceINeedToUse and IOtherService configuration here, then somehow rebuild the service tree.
         //Wow!
         return new OtherService(somevalue);
    });
}
public void Configure(IApplicationBuilder app)
    {
        //---------- Your code
        
        using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var resultLogic = serviceScope.ServiceProvider.GetService<IResultLogic>();
            resultLogic.YourMethod();
        }           

        //---------- Your code
    }