zoukankan      html  css  js  c++  java
  • 依赖注入

    服务生存期

    可以使用以下任一生存期注册服务:

    • 暂时
    • 作用域
    • 单例

    暂时

    暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。 向 AddTransient 注册暂时性服务。

    在处理请求的应用中,在请求结束时会释放暂时服务。

    即使同一个请求获取多次也会是不同的实例

    作用域

    作用域生存期服务针对每个客户端请求(连接)创建一次。 向 AddScoped 注册范围内服务。

    在处理请求的应用中,在请求结束时会释放有作用域的服务。和暂时生存期服务一样

    同一个请求获取多次会得到相同的实例

    使用 Entity Framework Core 时,默认情况下 AddDbContext 扩展方法使用范围内生存期来注册 DbContext 类型。

    不要从单一实例解析范围内服务。 当处理后续请求时,它可能会导致服务处于不正确的状态。 可以:

    • 从范围内或暂时性服务解析单一实例服务。
    • 从其他范围内或暂时性服务解析范围内服务。

    默认情况下在开发环境中,从具有较长生存期的其他服务解析服务将引发异常。

    要在中间件中使用范围内服务,请使用以下方法之一:

    • 将服务注入中间件的 Invoke 或 InvokeAsync 方法。 使用构造函数注入会引发运行时异常,因为它强制使范围内服务的行为与单一实例类似。
    • 使用基于工厂的中间件。 使用此方法注册的中间件按客户端请求(连接)激活,这也使范围内服务可注入中间件的 InvokeAsync 方法。
    public async Task InvokeAsync(HttpContext context,
        IOperationScoped scopedOperation)
    {
        _logger.LogInformation("Transient: " + _transientOperation.OperationId);
        _logger.LogInformation("Scoped: "    + scopedOperation.OperationId);
        _logger.LogInformation("Singleton: " + _singletonOperation.OperationId);
    
        await _next(context);
    }

    单例

    创建单例生命周期服务的情况如下:

    • 在首次请求它们时进行创建;或者
    • 在向容器直接提供实现实例时由开发人员进行创建。 很少用到此方法。

    每个后续请求都使用相同的实例。 如果应用需要单一实例行为,则允许服务容器管理服务的生存期。 不要实现单一实例设计模式,或提供代码来释放单一实例。 服务永远不应由解析容器服务的代码释放。 如果类型或工厂注册为单一实例,则容器自动释放单一实例。

    向 AddSingleton 注册单一实例服务。 单一实例服务必须是线程安全的,并且通常在无状态服务中使用。

    在处理请求的应用中,当应用关闭并释放 ServiceProvider 时,会释放单一实例服务。 由于应用关闭之前不释放内存,因此请考虑单一实例服务的内存使用。

    服务注册方法

    框架提供了适用于特定场景的服务注册扩展方法:

    服务注册方法
    方法自动
    对象
    释放
    多种
    实现
    传递参数
    Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()
    示例:
    services.AddSingleton<IMyDep, MyDep>();
    “是”
    Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION})
    示例:
    services.AddSingleton<IMyDep>(sp => new MyDep());
    services.AddSingleton<IMyDep>(sp => new MyDep(99));
    Add{LIFETIME}<{IMPLEMENTATION}>()
    示例:
    services.AddSingleton<MyDep>();
    AddSingleton<{SERVICE}>(new {IMPLEMENTATION})
    示例:
    services.AddSingleton<IMyDep>(new MyDep());
    services.AddSingleton<IMyDep>(new MyDep(99));
    AddSingleton(new {IMPLEMENTATION})
    示例:
    services.AddSingleton(new MyDep());
    services.AddSingleton(new MyDep(99));

     

    从 main 调用服务

    使用 IServiceScopeFactory.CreateScope 创建 IServiceScope 以解析应用范围内的作用域服务。 此方法可以用于在启动时访问有作用域的服务以便运行初始化任务。

    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
    
            using (var serviceScope = host.Services.CreateScope())
            {
                var services = serviceScope.ServiceProvider;
    
                try
                {
                    var myDependency = services.GetRequiredService<IMyDependency>();
                    myDependency.WriteMessage("Call services from main");
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred.");
                }
            }
    
            host.Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

    避免在 ConfigureServices 中调用 BuildServiceProvider。正确方法是使用选项模式对 DI 的内置支持:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie();
    
        services.AddOptions<CookieAuthenticationOptions>(
                            CookieAuthenticationDefaults.AuthenticationScheme)
            .Configure<IMyService>((options, myService) =>
            {
                options.LoginPath = myService.GetLoginPath();
            });
    
        services.AddRazorPages();
    }
  • 相关阅读:
    表格行内编辑增删改查
    rpc远程调用开发
    gdb调试程序
    Makefile文件编写
    CentOS6.6源码编译升级GCC至4.8.2
    linux 下C语言编程库文件处理与Makefile编写
    laravel队列-让守护进程处理耗时任务
    回顾javase点滴
    服务端生成word并压缩打包下载
    pytest框架插件(用例依赖、多重校验、执行顺序、失败重跑、重复执行、标记)
  • 原文地址:https://www.cnblogs.com/yetsen/p/13705405.html
Copyright © 2011-2022 走看看