翼度科技»论坛 编程开发 .net 查看内容

.net core IOC容器实现(一) -- ServiceDescriptor

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
IOC 容器内保存的程序运行过程中使用的服务实例。那么如果有些服务实例需要在运行时动态生成,比如,数据库连接,不可能在程序运行过程中所有线程共用一条数据库连接。所以 IOC 容器内保存的不是具体的服务实例,而是服务的相关信息,使用这个信息可以在程序运行时动态的生成服务实例,这些信息就保存在 ServiceDescriptor 类型的对象中。
属性
  1. //生命周期
  2. //Singleton 容器内有且只有一份
  3. //Scope 范围内只有一份,范围 可以使用 ServicePorvider.CreateScope 创建(可以将容器理解成树状结构每个Scope就是一个子容器),最常见的范围就是 Http 请求,每个请求算一个范围
  4. //Trasient 每次从IOC容器获取都是新的实例
  5. public ServiceLifetime Lifetime { get; }   
  6. //接口类型  接口类型和实现类型可以相同
  7. public Type ServiceType { get; }     
  8. //实现类型
  9. [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]public Type? ImplementationType { get; }         
  10. //实现实例  
  11. public object? ImplementationInstance { get; }   
  12. //实现类型工厂
  13. public Func<IServiceProvider, object>? ImplementationFactory { get; }
复制代码
构造函数


  • private 构造函数
    先介绍一个 private 的构造函数,个人认为这个构造函数设计为private有两个原因


  • 实例化出来的所有 ServiceDescriptor 对象都具有 serviceType 和 lifetime,所以这两个属性的赋值可以被单独剥离
  • 由于所有 ServiceDescriptor 必须要描述服务实例的构造方式,所以不能允许外部直接调用这个构造函数生成ServiceDescriptor实例,所以是 private 的

  • public 构造函数
    根据服务的生命周期和生成方式有三种不同的 public 的构造函数。


  • Singleton
  1. public ServiceDescriptor( Type serviceType,object instance)
  2.     : this(serviceType, ServiceLifetime.Singleton)
  3. {
  4.     //.....
  5.     ImplementationInstance = instance;
  6. }
复制代码

  • Scope 和 Trasient

    • 通过注入的实例类型通过反射获取

  1. public ServiceDescriptor(Type serviceType,Type implementationType,ServiceLifetime lifetime)
  2.             : this(serviceType, lifetime)
  3. {
  4.      // ....
  5.      ImplementationType = implementationType;
  6. }
复制代码



    • 通过传入的 构造工厂(委托)获取

  1. public ServiceDescriptor(
  2. Type serviceType,  //服务类型         
  3. Func<IServiceProvider, object> factory,       //创建服务的工厂     
  4. ServiceLifetime lifetime    //服务的生命周期
  5. ): this(serviceType, lifetime)   
  6. {                 
  7.     ImplementationFactory = factory;        
  8. }
复制代码
方法

ServiceDescriptor 里的方法都是静态方法,用于生成 ServiceDescriptor 实例。
核心 是要获取  注入的接口类型 和 实例类型或者生成实例的工厂,所以调用 Describe 方法之后,最终还是两个方法,一个保存了 接口类型和实例类型,一个保存了 接口类型和生成实例的工厂(),下面贴出来的是生成 Trasient 的 ServcieDescriptor 的方法,生成 Scope 和 Singleton 的与之类似
  1. //使用TService, TImplementation 生成 ServiceDescriptor(Transient)  
  2. // TService 接口类型
  3. // TImplementation 实现类型 继承 TService
  4. public static ServiceDescriptor Transient
  5. <TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>()            
  6. where TService : class            
  7. where TImplementation : class, TService        
  8. {            
  9.     return Describe<TService, TImplementation>(ServiceLifetime.Transient);        
  10. }
  11. // service 接口类型
  12. // implementationType 实现类型
  13. // lifetime 生命周期
  14. public static ServiceDescriptor Describe(            
  15.     Type serviceType,            
  16.     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType,            ServiceLifetime lifetime
  17. )        
  18. {            
  19.     return new ServiceDescriptor(serviceType, implementationType, lifetime);        
  20. }
复制代码
来源:https://www.cnblogs.com/ccwzl/archive/2023/06/02/17450049.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具