首页 > 其他分享 >如何更改已注册服务的生命周期?【转】

如何更改已注册服务的生命周期?【转】

时间:2023-06-19 21:00:11浏览次数:44  
标签:生命周期 服务 更改 descriptor 描述符 注册 services public

前言

我们知道在 ASP.NET Core 中,内置了一个依赖注入容器,可用于注册和解析服务。

在注册服务时,我们需要指定服务的生命周期:

  • Transient:每次请求服务时都会创建一个新的实例。

  • Scoped:每次请求服务时都会创建一个新的实例,但在同一个请求内,每次请求服务时都会使用同一个实例。

  • Singleton:每次请求服务时都会使用同一个实例。

但在某些情况下,比如由第三方库内置的扩展方法依赖注入,已注册的服务的生命周期可能不是我们想要使用的。

直接修改库的源代码是不可取的,因为这样做会导致在更新库时丢失更改。

解决思路

ASP.NET Core 依赖注入容器的接口定义如下:

public interface IServiceCollection : ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable, IList<ServiceDescriptor>

其中,ServiceDescriptor 是服务的描述符,它包含服务的类型、实现和生命周期:

public class ServiceDescriptor
{
    public Type? ImplementationType { get; }
    public object? ImplementationInstance { get; }
    public Func<IServiceProvider, object>? ImplementationFactory { get; }
    public ServiceLifetime Lifetime { get; }
    public Type ServiceType { get; }
}    

但是,这里的 Lifetime 属性是只读的,因此不能更改现有描述符的生命周期。

相反,我们可以获取并将其属性复制到新描述符中,并设置不同的新属性值,然后在依赖注入容器中删除旧描述符并添加新描述符。

实现

首先,我们需要一个扩展方法,它可以从集合中获取一个服务描述符:

public static class ServiceCollectionExtensions
{
    public static ServiceDescriptor GetServiceDescriptor<TService>(this IServiceCollection services)
    {
        return services.FirstOrDefault(d => d.ServiceType == typeof(TService));
    }
}

然后,我们需要一个扩展方法,它可以更改服务描述符的生命周期:

public static class ServiceCollectionExtensions
{
    public static IServiceCollection ChangeServiceLifetime<TService>(this IServiceCollection services, ServiceLifetime lifetime)
    {
        var descriptor = services.GetServiceDescriptor<TService>();
        if (descriptor != null)
        {
            services.Remove(descriptor);

            if (descriptor.ImplementationFactory == null)
            {
                services.Add(new ServiceDescriptor(
                    descriptor.ServiceType,
                    descriptor.ImplementationType,
                    lifetime
                ));
            }
            else
            {
                services.Add(new ServiceDescriptor(
                    descriptor.ServiceType,
                    descriptor.ImplementationFactory,
                    lifetime
                ));
            }                
        }
        return services;
    }
}

然后,我们就可以使用 ChangeServiceLifetime 方法更改服务的生命周期:

builder.Services.ChangeServiceLifetime<ISingletonService>(ServiceLifetime.Transient);

总结

通过本文,我们了解了如何更改已注册服务的生命周期。这是一个非常有用的技术,可以帮助我们更好地使用 ASP.NET Core 依赖注入容器。

标签:生命周期,服务,更改,descriptor,描述符,注册,services,public
From: https://www.cnblogs.com/fanfan-90/p/17492176.html

相关文章

  • kubernetes 生命周期问题分析
    1.Failed --pod里至少一个容器以非0code退出,说明应用有问题,需要debug应用容器2.pending--说明API对象已经被创建和保存在etcd数据库里,但是创建过程出了问题,可能是imagepull出问题,也可能是调度出了问题3.Unknow--说明pod的状态不能持续地被Kubelet发送给kubeapi,这很可能是......
  • Consul注册中心
    1.概念Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其它工具(比如ZooKeeper......
  • Spring高手之路5——彻底掌握Bean的生命周期
    1.理解Bean的生命周期1.1生命周期的各个阶段在SpringIOC容器中,Bean的生命周期大致如下:实例化:当启动Spring应用时,IOC容器就会为在配置文件中声明的每个<bean>创建一个实例。属性赋值:实例化后,Spring就通过反射机制给Bean的属性赋值。调用初始化方法:如果Bean配置了初始化方法,Spring......
  • 相同更改数据量的前提下,单次COMMIT和多次COMMIT对日志空间浪费的影响对比
    LGWR进程按照顺序写在线日志,中间不会跳跃,而且LGWR进程不会在同一个日志快写2次,即使一次写入的日志快只占几个字节,下次不会再用了,这就造成日志空间的浪费。Oracle做一次Commit,就会触发LGWR进程进行日志缓冲到日志文件的写入操作,因此可以说更改相同数据量的前提下,如果提交过于频繁,产......
  • Android应用开发者,你们真的了解Activity的生命周期吗?
    一开始,我觉得Activity的生命周期虽然过于复杂,但它不应该是一个难题。我的意思是:对于Android开发新手来说,如何正确地处理Activity生命周期可能有点困难,但是我无法想象对于那些富有经验的android开发者来说,这依然是一个棘手的问题。我还是想的太简单了。一会儿我会告诉你整个故事,但是......
  • 监听Activity生命周期方式及案例讲解
    本篇文章主要讲解如何快速实现Activity生命周期监听,以及其在官方lifecycle、第三方库Glide、PermissionX中的应用1.Activity生命周期监听Fragment实现Activity生命周期监听众所周知,Fragment中生命周期分发主要是依赖Activity,所以为了监听Activity的生命周期我们直接添加一个空的Fr......
  • 【Android】一文读懂 Activity 的生命周期
    作为Android开发人,如果说连Activity生命周期都没搞懂,会走非常多的弯路,所以这篇文章我就对Activity生命周期的生命周期进行一个简单的总结。单Activity生命周期的整体流程首先,我们创建一个My_A_Activity,并且打印它的各个生命周期方法。classMy_A_Activity:AppCompatActivity(){......
  • linux 定时任务 crontab更改当前用户
    1、参考CentOS7定时任务crontab入门Centos利用crontab定时执行任务及配置方法2、crontab-lcrontab-e#prodbackupdatabase#02***cd/data/xxxxx&&/usr/bin/shyy_backup.sh#prodautoupdatemanagecode#*****cd/data/xxxxx/&&sour......
  • Eureka注册中心
    1.注册中心服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用。主要用来存储服务信息,例如提供者url、路由信息等。服务注册中心是的微服务架构中最基础的设施之一。在微服务架构流行之前。注册中心就已经开始出现在分布式架构的系统中Dubbo是一个在国内比较......
  • 微信小程序更改刷新data 数组结构里的某一项数据
    如果每次setData 中list整个数组,感觉会消耗性能,所以只需要setData刷新对应的item  只需要通过以下方式解决    this.setData({'array[0].text':'updatedata'})//如果索引是动态的则使用下方方式varmMessage='array['+index+'].text';this.set......