项目框架构建之6:编写通用主机基础类

本文是“项目框架构建”系列之6,本文介绍如何编写通用主机基础类。

1.为了构建通用主机,我们先创建主机接口IAppHost接口

接口需要有配置项,我们定义为HostConfiguration,比如我们希望用户可以设定他的工作目录,就可以放在这里


接口需要有加载的.json的应用程序配置IConfiguration对象
接口还需要有服务管理器IServiceProvider对象
以及接口需要有日志管理ILoggerManager对象


2.构建主机,需要执行方法,所以我们添加了Build()和Run()两个方法
Build()方法是为了生成主机,这是必要方法。
Run()方法是为了启动应用程序,但这并不是必要的,因为主机生成后,您本身可以随时随地去启动你的程序。


3.生命周期以及事件

像主机这种底层结构,为了兼顾扩展性,我们需要提供周期的事件,以便让用户在启动的时候进行参与。


本程序抛砖引玉,提供了4个事件:
HostConfiguring:正在配置IConfiguration中,您可以继续加入其它初始化工作,如加载其它的.json文件
HostConfigurationInitialized:主机的配置已完成且抽象接口IConfiguration已构建
HostServicesInitializing:主机正在构建服务中,您可以继续加入其它服务一起构建
HostReady:主机构建完成已准备就绪


4.扩展依赖注入

为了防止重复添加服务,我们还需要扩展新增一些方法,用于防止重复添加服务。


5.扩展appsettings.cs文件的内容更改

程序运行后,有时可能需要在运行中修改appsettings.json中的配置,但IConfiguration本身不带有这种功能,所以我们需要自行编写扩展


6.编写主机接口IAppHost的抽象实现

我们是通用框架项目,所以需要提供一个抽象的基础实现,依据之前的设计,我们实现它的方法、事件、属性。

我们限定构造函数


程序初始化,初始化应用程序配置以及基础服务


编写Build()方法实现主机的生成


由于Run()函数不是必须的,所以我们把它定义为虚方法


 

下面通过编写事件的虚方法,以便子类能够参与过程

最后,附上完整的主机项目结构图:

也许各位朋友会想要源码,不要慌,等系列文章差不多了后,会开放源码下载。现在也没多少代码,没啥看头的。

下面附上IAppHost的具体实现:

using System;
using System.IO;
using Xejen.Hosting.Extensions;
using Xejen.Logger;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;namespace Xejen.Hosting
{/// <summary>/// <inheritdoc cref="IAppHost"/>基类 /// </summary>/// <creator>marc</creator>public abstract class AppHostBase : IAppHost{private readonly ILogger _logger;private readonly ILoggerManager _loggerManager;/// <inheritdoc cref="ILogger"/>protected ILogger Logger => _logger;/// <summary>/// 服务列表/// </summary>internal IServiceCollection Services;/// <inheritdoc cref="HostConfiguration"/>public HostConfiguration HostConfig { get; private set; }/// <inheritdoc/>public IConfiguration Configuration { get; private set; }/// <inheritdoc/>public IServiceProvider ServiceProvider { get; private set; }/// <inheritdoc/>public ILoggerManager LoggerManager => _loggerManager;/// <inheritdoc/>public event EventHandler<IConfigurationBuilder> HostConfiguring;/// <inheritdoc/>public event EventHandler<IConfiguration> HostConfigurationInitialized;/// <inheritdoc/>public event EventHandler<IServiceCollection> HostServicesInitializing;/// <inheritdoc/>public event EventHandler HostReady;/// <inheritdoc cref="AppHostBase"/>/// <param name="args">启动参数</param>/// <param name="loggerManager">采用的日志方式</param>protected AppHostBase(string[] args, ILoggerManager loggerManager) : this(loggerManager){HostConfig = HostConfiguration.Load(args);Initialize();}/// <summary>/// 将 ILoggerManager 添加到构造函数中/// </summary>/// <param name="loggerManager"><inheritdoc cref="ILoggerManager" path="/summary"/></param>private AppHostBase(ILoggerManager loggerManager){Check.NotNull(loggerManager, nameof(loggerManager));_loggerManager = loggerManager;_logger = _loggerManager.CreateLogger(typeof(AppHostBase));}/// <inheritdoc cref="AppHostBase"/>/// <param name="configuration"><inheritdoc cref="HostConfiguration" path="/summary"/></param>/// <param name="loggerManager"><inheritdoc cref="ILoggerManager" path="/summary"/></param>protected AppHostBase(HostConfiguration configuration, ILoggerManager loggerManager) : this(loggerManager){Check.NotNull(configuration, nameof(configuration));HostConfig = configuration;Initialize();}private void Initialize(){_logger.LogInformation($"应用程始启动,开始初始化");InitializeConfiguration(HostConfig.ConfigDirectory);InitializeServices();}/// <inheritdoc/>public IAppHost Build(){ConfigureServices(Services);ServiceProvider = Services.BuildServiceProvider();_logger.LogInformation($"服务初始化完毕,共 {Services.Count} 项服务");_logger.LogInformation($"程序初始化完毕");OnHostReady(this);return this;}/// <inheritdoc/>public virtual void Run() { }private void InitializeConfiguration(string configDirectory){_logger.LogInformation($"准备加载配置文件");if (string.IsNullOrEmpty(configDirectory)){configDirectory = AppDomain.CurrentDomain.BaseDirectory;}string appsettingFileName = HostConfig.DefaultSettingsFileName;if (!File.Exists(Path.Combine(configDirectory, appsettingFileName))){throw new FileNotFoundException($"未找到 {appsettingFileName} 文件,查找目录在:\r\n{configDirectory}");}var builder = new ConfigurationBuilder().SetBasePath(configDirectory).AddJsonFile(appsettingFileName, optional: true, reloadOnChange: true);ConfigureJsonFiles(builder);OnHostConfiguring(this, builder);Configuration = builder.Build();OnHostConfigurationInitialized(this, Configuration);_logger.LogInformation($"配置文件加载完成,工作目录: {configDirectory}");}/// <summary>/// 配置json文件,基类已自动完成<see langword="appsettings.json"/>文件的加载,您只需加载您其它的配置文件即可/// </summary>/// <param name="configuration">传入过来的<see cref="IConfigurationBuilder"/>接口对象</param>protected virtual void ConfigureJsonFiles(IConfigurationBuilder configuration){}/// <summary>/// 初始化基础服务/// </summary>private void InitializeServices(){_logger.LogInformation($"准备初始化服务");var services = new ServiceCollection();Services = services;// 添加服务// services.AddTransient<IService, ServiceImplementation>();// 添加主机服务:public class AppHostedService : IHostedService,该类要实现StartAsync以及StopAsync方法// services.AddHostedService<AppHostedService>();services.AddSingleton(_loggerManager);services.AddSingleton(Configuration);services.AddSingleton(HostConfig);OnHostServicesInitializing(this, services);}/// <summary>/// 配置服务,各子项目可以重写此方法来注册各项服务/// </summary>/// <param name="services">服务集合</param>protected virtual void ConfigureServices(IServiceCollection services){}/// <inheritdoc cref="HostConfiguring" path="/summary"/>/// <param name="sender"><inheritdoc cref="IAppHost" path="/summary"/></param>/// <param name="builder">用于构建应用程序配置的构建器</param>protected virtual void OnHostConfiguring(IAppHost sender, IConfigurationBuilder builder){HostConfiguring?.Invoke(sender, builder);}/// <inheritdoc cref="HostConfigurationInitialized" path="/summary"/>/// <param name="sender"><inheritdoc cref="IAppHost" path="/summary"/></param>/// <param name="builder">应用程序配置</param>protected virtual void OnHostConfigurationInitialized(IAppHost sender, IConfiguration builder){HostConfigurationInitialized?.Invoke(sender, builder);}/// <inheritdoc cref="HostServicesInitializing" path="/summary"/>/// <param name="sender"><inheritdoc cref="IAppHost" path="/summary"/></param>/// <param name="builder">服务列表</param>protected virtual void OnHostServicesInitializing(IAppHost sender, IServiceCollection builder){HostServicesInitializing?.Invoke(sender, builder);}/// <inheritdoc cref="HostReady" path="/summary"/>/// <param name="sender"><inheritdoc cref="IAppHost" path="/summary"/></param>protected virtual void OnHostReady(IAppHost sender){HostReady?.Invoke(sender, EventArgs.Empty);}}
}

祝您用餐愉快,下一篇我们将编写如何使用主机框架的实际应用,敬请期待

1-3-5 $ 3-5-5-4 带着田螺回四堡 3-5-2-4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/606739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习|4.7 参数和超参数

4.7 参数和超参数 超参数是指需要用户提前设置好的参数&#xff0c;这些超参数最终会影响到参数的数值&#xff08;相当于参数是动态调整得到的&#xff09; 学习率的选取 最优学习率应该能使得代价函数趋于一个较低的常数。

接口工具Apifox

最近发现一款接口测试工具--apifox&#xff0c;我我们很难将它描述为一款接口管理工具 或 接口自测试工具。 官方给了一个简单的公式&#xff0c;更能说明apifox可以做什么。 Apifox Postman Swagger Mock JMeter Apifox的特点&#xff1a; 接口文档定义&#xff1a; Apif…

CSS 发光输入框动画

<template><view class="content"><input placeholder="请输入..." class="input" /> </view> </template><script></script><style>/* 设置整个页面的背景颜色为 #212121 */body{background-c…

react native中使用tailwind并配置自动补全

使用的第三方库是tailwind-react-native-classnames&#xff0c;同类的也有tailwind-rn&#xff0c;但是我更喜欢前者官方demo&#xff1a; import { View, Text } from react-native; import tw from twrnc;const MyComponent () > (<View style{twp-4 android:pt-2 b…

【办公技巧】excel中设置选项按钮的方法

大家是否会遇到需要勾中选项的情况&#xff0c;我们可以在电子表格中制作出可以勾选、选中的选项按钮&#xff0c;今天我们一起学习一下设置方法。 首先&#xff0c;我们需要先在excel工具栏中添加一个功能模块&#xff1a;开发工具 依次点击excel中的文件 – 选项 – 自定义…

第二百五十三回

文章目录 概念介绍使用方法示例代码 概念介绍 进度条是常用的组件之一&#xff0c;它主要用来显示某种动作的完成进度。Flutter提供了多种进度条组件&#xff0c;常用的是水平进度条&#xff1a;LinearProgressIndicator&#xff1b;圆形进度条 :CircularProgressIndicator和R…

2023年,To B资本航船走向哪了?

国内To B领域在去掉泡沫、结束资本狂欢之后&#xff0c;投资决策愈加理性。但与此同时&#xff0c;下滑的步伐正在放慢&#xff0c;交易数量和金额的降低逐渐放缓&#xff0c;市场逐渐走向稳定。 作者|斗斗 编辑|皮爷 出品|产业家 2023年&#xff0c;在一众业内人士的眼中&…

文件系统与日志分析

一&#xff0c;文件系统 &#xff08;一&#xff09;inode 和block概述 1&#xff0c;文件数据包括元信息与实际数据 2&#xff0c;文件存储在硬盘上&#xff0c;硬盘最小存储单位是“扇区”&#xff0c;每个扇区存储512字节 3&#xff0c;block (块) 连续的八个扇区组成一…

从零开始了解Figma:全面介绍这款设计工具,让你熟练运用!

什么是Figma&#xff1f; 它是一个类似于Sketch或XD的UI设计工具&#xff0c;但Figma和后两者的本质区别在于它是基于web的&#xff0c;也就是说&#xff0c;只要有浏览器和网络&#xff0c;它就可以打开和使用。 Figma为什么强大&#xff1f; Windows上最好的UI设计工具 由…

Redisson 源码解析 - 分布式锁实现过程

一、Redisson 分布式锁源码解析 Redisson是架设在Redis基础上的一个Java驻内存数据网格。在基于NIO的Netty框架上&#xff0c;充分的利用了Redis键值数据库提供的一系列优势&#xff0c;在Java实用工具包中常用接口的基础上&#xff0c;为使用者提供了一系列具有分布式特性的常…

一文搞定JMM核心原理

公众号《鲁大猿》&#xff0c;寻精品资料&#xff0c;帮你构建Java全栈知识体系 www.jiagoujishu.cn &#xff08;架构技术.cn&#xff09; JMM引入 从堆栈说起 JVM内部使用的Java内存模型在线程栈和堆之间划分内存。 此图从逻辑角度说明了Java内存模型&#xff1a; # 堆栈里…

SpringBoot + Mybatis 实现多数据源原来如此简单

1、为什么需要整合多数据源 在开发的过程中&#xff0c;我们可能会遇到一个工程使用多个数据源的情况&#xff0c;总体而言分为以下几个原因 a、数据隔离&#xff1a;将不同的数据存储在不同的数据库中&#xff0c;如多租户场景 b、性能优化&#xff1a;将数据分散到多个数据库…

【野火i.MX6ULL开发板】利用microUSB线烧入Debian镜像

0、前言 烧入Debian镜像有两种方式&#xff1a;SD卡、USB SD卡&#xff1a;需要SD卡&#xff08;不是所有型号都可以&#xff0c;建议去了解了解&#xff09;、SD卡读卡器 USB&#xff1a;需要microUSB线 由于SD卡的网上资料很多了&#xff0c;又因为所需硬件&#xff08;SD卡…

Spring应用的部署与管理

一、前言 部署是将开发好的应用发布到服务器上&#xff0c;使其能够被用户访问的关键步骤。Spring框架提供了灵活的部署选项&#xff0c;本文将介绍Spring应用的常见部署方式和一些建议&#xff0c;帮助开发者顺利将应用投放到生产环境。 二、传统部署方式&#xff1a;WAR包 传…

09Bean的生命周期及循环依赖

Spring其实就是一个管理Bean对象的工厂。它负责对象的创建&#xff0c;对象的销毁等。 所谓的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程。 Bean的生命周期之5步 ● 第一步&#xff1a;实例化Bean(无参构造方法执行) ● 第二步&#xff1a;Bean属性赋值(注…

基于YOLOv7算法的高精度实时19类动物目标检测识别系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法的高精度实时19类动物目标检测系统可用于日常生活中检测与定位19类动物目标&#xff08;水牛、 斑马、 大象、 水豚、 海龟、 猫、 奶牛、 鹿、 狗、 火烈鸟、 长颈鹿、 捷豹、 袋鼠、 狮子、 鹦鹉、 企鹅、 犀牛、 羊和老虎&#xff09;&#x…

[Kubernetes]5. k8s集群StatefulSet详解,以及数据持久化(SC PV PVC)

前面通过deployment结合service来部署无状态的应用,下面来讲解通过satefulSet结合service来部署有状态的应用 一.StatefulSet详解 1.有状态和无状态区别 无状态: 无状态(stateless)、牲畜(cattle)、无名(nameless)、可丢弃(disposable) 有状态: 有状态(stateful)、宠物(pet)…

【Python机器学习】构造决策树

通常来说&#xff0c;构造决策树直到所有叶结点都是纯的叶结点&#xff0c;但这会导致模型非常复杂&#xff0c;并且对于训练数据高度过拟合。 为了防止过拟合&#xff0c;有两种常见策略&#xff1a; 1、尽早停止树的生长&#xff0c;也叫预剪枝 2、先构造树&#xff0c;但…

系统架构设计师教程(十)软件可靠性基础知识

软件可靠性基础知识 10.1 软件架构演化和定义的关系10.1.1 演化的重要性10.1.2 演化和定义的关系 10.2 面向对象软件架构演化过程10.2.1 对象演化10.2.2 消息演化10.2.3 复合片段演化10.2.4 约束演化 10.3 软件架构演化方式的分类10.3.1 软件架构演化时期10.3.2 软件架构静态演…

免费服务器腾讯云_腾讯云免费服务器申请流程(2024更新)

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM&#xff0c;轻量配置可选2核2G3M、2核8G7M和4核8G12M&#xff0c;CVM云服务器可选2核2G3M和2核4G3M配置&#xff0c;腾讯云百科txybk.com分享2024年最新腾讯云免费服务器…