首页 > 其他分享 >Util应用框架核心(三) - 服务注册器

Util应用框架核心(三) - 服务注册器

时间:2023-10-31 20:00:14浏览次数:31  
标签:服务 框架 ServiceRegistrarConfig 配置 Util 注册器 public

本节介绍服务注册器的开发.

如果你不需要扩展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 方法之前禁用服务注册器.

标签:服务,框架,ServiceRegistrarConfig,配置,Util,注册器,public
From: https://www.cnblogs.com/xiadao521/p/17801200.html

相关文章

  • 框架记录
     流程表流程节点设置表:Sys_WorkFlowStepStepType存的是“审批类型,1、用户;2角色”  如果StepType是1(用户)StepValue存的是用户id,如果StepType是2(角色)存的是角色ID 具体某个业务的流程表:Sys_WorkFlowTableStep......
  • 使用hardhat框架,将合约部署到Sepolia测试网中
    1.在hardhat.config.js中写入sepolia的测试网路径,以及自己私有钱包的密钥将自己的默认网络设置为测试网的网络,注意solidity的版本号要保持一致 2.在.env文件中填写基本参数,添加dotenv便于读  3.在etherscan.io/myapikey里面获取自己的apikey并添加到.env中 注意:在用ha......
  • java实现文件夹上传功能实例代码(SpringBoot框架)
    前言有时我们后台管理等服务可能会有这样一个简单需求,就是根据文件夹将整个文件夹下的所有资源都上传到我们的服务器上,本人也是搜索了大量资料,最终以最简单便捷的方式实现该功能,具体操作步骤如下一、前端如何设置上传组件并将资源上传到后台服务这里的项目框架为若依VUE版本......
  • KFC框架:小游戏/H5 首包、分包、加载优化方案与项目示例
    CocosCreator小游戏/H5首包、分包、加载优化方案与项目示例今天是疯狂星期四,给大家晒一下最近的成果。麒麟子上周末将《Jare大冒险》升级到了CocosCreator3.8,并更新到了CocosStore。在做了更精细的分包管理、资源加载拆分,以及利用分析工具剔除了不必要的资源加载后,最终......
  • 第十章 数据库连接池与DBUtils工具
    目录一.单选题(共5题,50分)二.判断题(共5题,50分)一.单选题(共5题,50分)(单选题)已知,存在QueryRunner对象runner,SQL语句:Stringsql="select*fromuserwhereid=?";下面操作中,能实现查询指定记录的选项是()A.Useruser=(User)runner.query(sql,newBeanListHandler(User.c......
  • pytest框架
    pytest安装a)安装pipinstallpytestb)验证安装pytest--version1、pytest的⽤例运⾏规则1)pytest将在当前⽬录及其⼦⽬录中运⾏所有格式为test.py或者test.py⽂件2)测试⽅法/测试函数默认必须是test开头3)测试类必须是Test开头4)测试类不能有构造⽅法init,会影响用......
  • 技术漫谈|IVR通用开发框架简说
     IVR为InteractiveVoiceResponse的缩写,意为交互式语音应答(系统)。它可以应答客户的呼叫,然后为呼叫者提供语音导航或自助服务,呼叫者可通过按键输入或使用语音命令进行选择。随后,IVR可通过呼叫路由将呼叫转移到座席或自助服务应用程序。在金融领域,IVR应用系统也被银行称之为电话......
  • 技术漫谈|IVR通用开发框架简说
    IVR为InteractiveVoiceResponse的缩写,意为交互式语音应答(系统)。它可以应答客户的呼叫,然后为呼叫者提供语音导航或自助服务,呼叫者可通过按键输入或使用语音命令进行选择。随后,IVR可通过呼叫路由将呼叫转移到座席或自助服务应用程序。在金融领域,IVR应用系统也被银行称之为电话银行......
  • 于璠访谈录 | AI 框架应该和而不同?
    点击以下链接收听本期“大咖访谈”播客,与大咖面对面:https://www.xiaoyuzhoufm.com/episodes/653f236d21aad9875428c3f2++刘天栋++:访谈主持,开源雨林社区顾问、开源社联合创始人、ASFmember++于璠++:访谈嘉宾,昇思MindSpore技术总经理,AIforScience实验室主任:::hljs-cen......
  • binutils 2.40 Linker (ld) 官方文档下载
    前言最近需要熟悉elf与共享库的链接与加载流程,需要先了解elf文件是怎么链接的,链接脚本如何阅读最有效的方式是查看GNU官方的Linker(ld)文档,通过查找,这个Linker(ld)属于GNUbinutils,当前的较新的版本为:2.40binutilsLinker(ld)文档文档地址:https://sourceware.o......