Util应用框架核心(三) - 服务注册器
本节介绍服务注册器的开发.
如果你不需要扩展Util应用框架,直接跳过.
当你把某些功能封装到自己的类库,并希望启动时自动执行初始化代码进行配置时,定义服务注册器.
服务注册器概述
服务注册器是Util项目启动时自动执行的代码块.
Util应用框架的某些类库使用服务注册器进行配置,比如 Util.ObjectMapping.AutoMapper .
当你引用 Util.ObjectMapping.AutoMapper 类库,不需要进行任何配置就可以直接使用 AutoMapper 的基本功能.
定义服务注册器
服务注册器只需实现 Util.Infrastructure.IServiceRegistrar 接口,启动器会扫描查找它.
你可以把服务注册器放在任何地方,不过放在约定的位置会更容易维护.
约定: 服务注册器名称以 ServiceRegistrar 结尾,放到 Infrastructure 目录中.
IServiceRegistrar 接口代码
/// <summary>
/// 服务注册器
/// </summary>
public interface IServiceRegistrar {
/// <summary>
/// 排序号
/// </summary>
int OrderId { get; }
/// <summary>
/// 是否启用
/// </summary>
bool Enabled {
get;
}
/// <summary>
/// 注册服务,该操作在启动开始时执行,如果需要延迟执行某些操作,可在返回的Action中执行,它将在启动最后执行
/// </summary>
/// <param name="context">服务上下文</param>
Action Register( ServiceContext context );
}
/// <summary>
/// 服务上下文
/// </summary>
public class ServiceContext {
/// <summary>
/// 初始化服务上下文
/// </summary>
/// <param name="hostBuilder">主机生成器</param>
/// <param name="assemblyFinder">程序集查找器</param>
/// <param name="typeFinder">类型查找器</param>
public ServiceContext( IHostBuilder hostBuilder, IAssemblyFinder assemblyFinder, ITypeFinder typeFinder ) {
HostBuilder = hostBuilder ?? throw new ArgumentNullException( nameof( hostBuilder ) );
AssemblyFinder = assemblyFinder ?? throw new ArgumentNullException( nameof( assemblyFinder ) );
TypeFinder = typeFinder ?? throw new ArgumentNullException( nameof( typeFinder ) );
}
/// <summary>
/// 主机生成器
/// </summary>
public IHostBuilder HostBuilder { get; }
/// <summary>
/// 程序集查找器
/// </summary>
public IAssemblyFinder AssemblyFinder { get; }
/// <summary>
/// 类型查找器
/// </summary>
public ITypeFinder TypeFinder { get; }
}
注册服务
Register 方法用于定义服务配置.
Register 方法传递服务上下文 ServiceContext 参数,除了可以获得主机生成器 IHostBuilder 外,还可以获取类型查找器 ITypeFinder.
你可以在服务注册器中查找某些类型,并进行配置,比如查找 ISingletonDependency 接口的实现类,并配置单例依赖关系.
Register 方法的返回类型是一个委托 Action.
如果希望服务配置方法立即执行,返回 null.
如果希望服务注册器延迟到最后执行,返回委托.
启用服务注册器
只有已启用的服务注册器才会生效 .
服务注册器的执行顺序
通常服务注册器用来配置服务的依赖注入关系,执行顺序不太重要.
不过如果你的服务注册器依赖执行顺序,需要在某些服务注册器的前面或后面执行,可以设置排序号 OrderId.
启动器使用排序号对服务注册器进行排序, OrderId 越小的先执行.
此外,如果你需要将服务注册器延迟到最后执行,可以让 Register 方法返回委托.
启动器在执行服务注册器 Register 方法后保存返回的委托实例列表.
在执行委托实例之前,启动器可能会执行其它操作.
在之前的版本会配置依赖注册器,不过它的作用有限,已经删除,未来可能添加其它操作.
禁用和启用服务注册器
当引用包含服务注册器的类库,启动时会自动运行初始化配置代码.
对于大部分场景都是预期行为.
不过有些时候自动执行服务注册器会导致问题,你需要禁用它.
服务注册器配置 Util.Infrastructure.ServiceRegistrarConfig 用于禁用和启用服务注册器.
ServiceRegistrarConfig 使用 AppContext.SetSwitch 方法来完成禁用和启用.
/// <summary>
/// 服务注册器配置
/// </summary>
public class ServiceRegistrarConfig {
/// <summary>
/// 服务注册器配置实例
/// </summary>
public static readonly ServiceRegistrarConfig Instance = new ();
/// <summary>
/// 禁用服务注册器
/// </summary>
/// <param name="serviceName">服务注册器名称</param>
public static void Disable( string serviceName ) {
AppContext.SetSwitch( serviceName, false );
}
/// <summary>
/// 启用服务注册器
/// </summary>
/// <param name="serviceName">服务注册器名称</param>
public static void Enable( string serviceName ) {
AppContext.SetSwitch( serviceName, true );
}
/// <summary>
/// 是否启用
/// </summary>
/// <param name="serviceName">服务注册器名称</param>
public static bool IsEnabled( string serviceName ) {
var result = AppContext.TryGetSwitch( serviceName, out bool isEnabled );
if ( result && isEnabled == false )
return false;
return true;
}
}
直接传递服务名称不太方便,可以在 ServiceRegistrarConfig 上定义扩展方法来禁用和启用服务注册器.
服务注册器范例
下面以 Util.ObjectMapping.AutoMapper 类库的服务注册器为例进行说明.
在服务注册器定义服务名称,一般使用带命名空间的服务注册器类名.
设置排序号.
Enabled属性使用 ServiceRegistrarConfig 配置的 IsEnabled 方法,默认为启用状态,可以通过 ServiceRegistrarConfig 禁用它.
Register 方法使用类型查找器查找所有实现了 IAutoMapperConfig 接口的配置实例并进行配置.
创建 AutoMapper ObjectMapper 对象,并传递给 MapTo 扩展类.
最后,通过主机生成器 ConfigureServices 配置 IObjectMapper 单例服务.
/// <summary>
/// AutoMapper服务注册器
/// </summary>
public class AutoMapperServiceRegistrar : IServiceRegistrar {
/// <summary>
/// 获取服务名
/// </summary>
public static string ServiceName => "Util.ObjectMapping.Infrastructure.AutoMapperServiceRegistrar";
/// <summary>
/// 排序号
/// </summary>
public int OrderId => 300;
/// <summary>
/// 是否启用
/// </summary>
public bool Enabled => ServiceRegistrarConfig.IsEnabled( ServiceName );
/// <summary>
/// 注册服务
/// </summary>
/// <param name="serviceContext">服务上下文</param>
public Action Register( ServiceContext serviceContext ) {
var types = serviceContext.TypeFinder.Find<IAutoMapperConfig>();
var instances = types.Select( type => Reflection.CreateInstance<IAutoMapperConfig>( type ) ).ToList();
var expression = new MapperConfigurationExpression();
instances.ForEach( t => t.Config( expression ) );
var mapper = new ObjectMapper( expression );
ObjectMapperExtensions.SetMapper( mapper );
serviceContext.HostBuilder.ConfigureServices( ( context, services ) => {
services.AddSingleton<IObjectMapper>( mapper );
} );
return null;
}
}
服务注册器配置扩展范例
定义服务注册器配置扩展
在 ServiceRegistrarConfig 扩展特定的启用和禁用方法,并封装服务名.
/// <summary>
/// AutoMapper服务注册器配置扩展
/// </summary>
public static class ServiceRegistrarConfigExtensions {
/// <summary>
/// 启用AutoMapper服务注册器
/// </summary>
/// <param name="config">服务注册器配置</param>
public static ServiceRegistrarConfig EnableAutoMapperServiceRegistrar( this ServiceRegistrarConfig config ) {
ServiceRegistrarConfig.Enable( AutoMapperServiceRegistrar.ServiceName );
return config;
}
/// <summary>
///禁用AutoMapper服务注册器
/// </summary>
/// <param name="config">服务注册器配置</param>
public static ServiceRegistrarConfig DisableAutoMapperServiceRegistrar( this ServiceRegistrarConfig config ) {
ServiceRegistrarConfig.Disable( AutoMapperServiceRegistrar.ServiceName );
return config;
}
}
使用服务注册器配置扩展
下面演示禁用 Util.ObjectMapping.Infrastructure.AutoMapperServiceRegistrar 服务注册器.
ServiceRegistrarConfig.Instance.DisableAutoMapperServiceRegistrar();
builder.AsBuild().AddUtil();
应在 AddUtil 方法之前禁用服务注册器.
Util应用框架核心(三) - 服务注册器的更多相关文章
- [ASP.NET Core 3框架揭秘] 依赖注入[6]:服务注册
通过<利用容器提供服务>我们知道作为依赖注入容器的IServiceProvider对象是通过调用IServiceCollection接口的扩展方法BuildServiceProvider创 ...
- 微服务架构 | *3.5 Nacos 服务注册与发现的源码分析
目录 前言 1. 客户端注册进 Nacos 注册中心(客户端视角) 1.1 Spring Cloud 提供的规范标准 1.2 Nacos 的自动配置类 1.3 监听服务初始化事件 AbstractAu ...
- 服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)
在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一 ...
- Spring Cloud Alibaba 实战 之 Nacos 服务注册和发现
服务注册与发现,服务发现主要用于实现各个微服务实例的自动化注册与发现,是微服务治理的核心,学习 Spring Cloud Alibaba,首先要了解框架中的服务注册和发现组件——Nacos. 一.Sp ...
- 如何优化Spring Cloud微服务注册中心架构?
作者: 石杉的架构笔记 1.再回顾:什么是服务注册中心? 先回顾一下什么叫做服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相 ...
- 搞懂Dubbo服务发布与服务注册
一.前言 本文讲服务发布与服务注册,服务提供者本地发布服务,然后向注册中心注册服务,将服务实现类以服务接口的形式提供出去,以便服务消费者从注册中心查阅并调用服务. 本文源码分析基于org.apache ...
- ASP.NET Core依赖注入系统学习教程:关于服务注册使用到的方法
在.NET Core的依赖注入框架中,服务注册的信息将会被封装成ServiceDescriptor对象,而这些对象都会存储在IServiceCollection接口类型表示的集合中,另外,IServi ...
- SpringCloud的服务注册中心(四)- 高可用服务注册中心的搭建
一.双 服务注册注册中心 1.服务注册中心的服务端 - EurekaServer 1.1.EurekaServer1 String.application.name=eureka-server ser ...
- Nacos服务注册与发现的2种实现方法!
Spring Cloud Alibaba 技术体系中的 Nacos,提供了两个重要的功能:注册中心(服务注册与发现)功能和配置中心功能. 其中注册中心解决了微服务调用中,服务提供者和服务调用者的解耦, ...
- SpringCloud核心教程 | 第三篇:服务注册与发现 Eureka篇
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...
随机推荐
- Tauri-Admin通用后台管理系统|tauri+vue3+pinia桌面端后台EXE
基于tauri+vite4+pinia2跨端后台管理系统应用实例TauriAdmin. tauri-admin 基于最新跨端技术 Tauri Rust webview2 整合 Vite4 构建桌面端通 ...
- pgrep:根据名称或其他属性查找进程(查找系统中running状态的进程)
用法示例 # 根据名称过滤 dewan Work ~/code/shell% pgrep qemu 3570191 dewan Work ~/code/shell% pgrep qemu -l 357 ...
- Fastjson1.2.24漏洞复现-基于vulhub漏洞平台(文件上传写入-反弹shell)
Fastjson1.2.24漏洞复现-基于vulhub漏洞平台 环境准备: 192.168.59.130 攻击机 window10 192.168.59.135 靶机 centos8 声明:不涉及互联 ...
- 洛谷 Luogu P1038 [NOIP2003 提高组] 神经网络
这题看着很吓人实则很简单.求输出层,正着求很麻烦,因为知不道谁连向这个点,所以可以反向建边,反着求. 拓扑+dfs,时间复杂度 \(\text{O(n + m)}\) #include <ios ...
- #Powerbi 1分钟学会利用AI,为powerbi报表进行高端颜色设计
在BI报表的设计中,配色方案往往成为一大难题,一组切合主题.搭配合理的颜色设计往往能为我们的报表,加分不少. 今天,就介绍一个AI配色的网站,利用AI为pbi报表进行配色设计. 一:网站网址 http ...
- 论文解读(DWL)《Dynamic Weighted Learning for Unsupervised Domain Adaptation》
[ Wechat:Y466551 | 付费咨询,非诚勿扰 ] 论文信息 论文标题:Dynamic Weighted Learning for Unsupervised Domain Adaptatio ...
- c++中unique_ptr 的使用和理解
unique_ptr 的使用 std::unique_ptr是c++11起引入的智能指针,为什么必须要在c++11起才有该特性,主要还是c++11增加了move语义,否则无法对对象的所有权进行传递. ...
- GitHub Deskhub使用
(适合已经知道git是啥但是还不太熟到同学看-) GitHub deskhub就是一个图形化的github管理工具啦,比起来命令行使用舒服100倍哈哈哈- 链接:https://desktop.git ...
- cockpit--一款开源的适用于单主机的Linux监控面板
在搜索Linux监控时,偶然发现一款还不错的监控面板,该面板为red hat开发,适用于各种Linux发行版,部署也非常方便,官方文档Running Cockpit - Cockpit Project ...
- 《Linux基础》02. 目录结构 · vi、vim · 关机 · 重启
@ 目录 1:目录结构 2:vi.vim快速入门 2.1:vi 和 vim 的三种模式 2.1.1:一般模式 2.1.2:编辑模式 2.1.3:命令模式 2.2:常用快捷键 2.2.1:一般模式 2. ...