c++ dll 类使用_在.Net Core 中使用钩子

目录

  • 前言
  • 什么是钩子
  • 使用钩子
  • 3. 挂载多个钩子
  • 4. 在钩子中加载额外的程序集
  • 5. 在 Asp.Net Web Api 项目中使用钩子
  • 结束语
  • 演示代码下载

前言

    Host startup hook,是2.2中提供的一项新的功能,通过使用主机启动钩子,允许开发人员在不修改代码的情况下,在服务启动之前注入代码;通过使用钩子,可以对已部署好的服务在服务启动期间自定义托管程序的行为;通过使用钩子,可以对服务进行跟踪或者遥测,也可以在服务启动前对托管环境进行健康检查;还可以通过钩子动态加载程序集进行依赖注入等功能。

什么是钩子

钩子的作用原理是通过设置环境变量 DOTNET_STARTUP_HOOKS 的值将钩子程序挂载到托管程序之中,在托管程序启动的时候,CoreCLR 将按照钩子列表顺序进行检查,初始化后执行每个钩子程序,当钩子列表中的钩子程序被逐一执行完成后,托管程序将返回到程序主入口 Main 方法,进入一系列的启动,钩子程序可以是任何 .Net Core 版本的类库项目,在项目内必须包含类 StartupHook 这是固定命名,且 StartupHook 必须是一个没有命名空间的内部类,包含默认的静态方法 Initialize(),符合此规范即可作为钩子程序进行托管挂载

使用钩子

1.首先创建一个控制台项目 Ron.HooksDemo ,作为托管主机,用于挂载钩子程序 Ron.Init

Ron.HooksDemo 的代码非常简单,仅仅输出一句话

    class Program    {        static void Main(string[] args)        {            Console.WriteLine("程序已启动");            Console.ReadKey();        }    }

2. 创建钩子程序,Ron.Init

2.1 按照钩子程序的规范,创建一个无命名空间的内部类 StartupHook ,且包含默认静态方法 Initialize()

internal class StartupHook{    public static void Initialize()    {        Console.WriteLine("程序集:Ron.Init.dll");        Console.WriteLine("正在获取服务器信息.....");        string[] drives = Environment.GetLogicalDrives();        Console.WriteLine("machineName:{0},OSVersion:{1},version:{2},userName:{3},CurrentDirectory:{4}Core Count:{5}WorkSet:{6}Drives:{7}",            Environment.MachineName,            Environment.OSVersion,            Environment.Version,            Environment.UserName,            Environment.CurrentDirectory,            Environment.ProcessorCount,            Environment.WorkingSet,            string.Join(",", drives));        Console.WriteLine("正在获取网络配置.....");        var hostName = Dns.GetHostName();        Console.WriteLine("HostName:{0}", hostName);        var addresses = Dns.GetHostAddresses(hostName);        foreach (var item in addresses)        {            IPAddress ip = item.MapToIPv4();            Console.WriteLine("AddressFamily:{0} Address:{1}", ip.AddressFamily, ip);        }        Console.WriteLine("正在上报启动信息.....");        Console.WriteLine("=========== Ron.Init.dll 结束 ===========");    }}

上面的代码即表示一个标准的钩子程序,在 Initialize() 内部,进行托管主机检查,获取网络配置等行为,最好,还打印一条上报到遥测服务器的信息,这里是模拟上报检查报告,最后输出结束信息代码非常检查,现在打开 Ron.HooksDemo 项目属性页进行钩子挂载

b3e6e4a8179db98cfd853ff6f9a2ab74.png

上图添加环境变量 DOTNET_STARTUP_HOOKS ,并设置其值为 C:甥敳獲AdministratorSourceReposRon.HooksDemoRon.InitbinDebugetcoreapp2.2Ron.Init.dll,这是本次示例的钩子程序绝对路径注意:该环境变量的值不支持相对路径,如果尝试使用相对路径,托管主机将抛出 ArgumentException 异常

2.2 运行程序,看看是否正确挂载了钩子程序 Ron.Init

5fbf0606c94c7d29b014e949013c9094.png

上图红色部分输出信息表示钩子程序挂载成功,蓝色部分表示托管主机已启动,可以看到,托管主机启动是在挂载钩子之后运行的一定要注意,钩子是在托管程序的 Main 方法之前运行的

3. 挂载多个钩子

3.1 一个托管程序可以挂载多个钩子

挂载多个钩子的方法是设置环境变量 DOTNET_STARTUP_HOOKS 的值,多个钩子按顺序执行,其中 Windows 和 Unix 挂载多个钩子的方式基本相同,这其中,有一点微小的区别

  • Windows 平台挂载方式
DOTNET_STARTUP_HOOKS = C:Hooks_1.dll;C:Hooks_2.dll
  • Unix 平台挂载方式
DOTNET_STARTUP_HOOKS =/data/Hooks_1.dll:/data/Hooks_2.dll

以上 DOTNET_STARTUP_HOOKS 变量的值包含两个钩子程序,其中 Windows 平台的值为使用分号(;)进行分隔,Unix 平台使用冒号(:)进行分隔,这于传统使用方式一致

3.2 运行挂载了多个钩子的托管程序

  • 下面把两个钩子挂载到 Ron.HooksDemo 项目后,他们分别是:Ron.Init 和 Ron.License

Ron.Init 钩子输出的是检查服务器信息,这个信息在之前已经演示,这里不再重复,下面看 Ron.License 代码

    public static void Initialize()    {        Console.WriteLine("程序集:Ron.License.dll");        Console.WriteLine("作者:Ron.liang");        Console.WriteLine("博客地址:https://www.cnblogs.com/viter/");        Console.WriteLine("=========== Ron.License.dll 结束 ===========");    }
  • 钩子程序的 Ron.License 代码也非常简单,结构和 Ron.Init 钩子程序一致,只是简单的输出版权信息

3.3 运行 Ron.HooksDemo 程序,看下图输出结果

223f4f534b16ea858bf9c9af8466f4e4.png

红色部分是 Ron.Init 钩子输出信息,黄色部分是 Ron.License 输出信息,蓝色部分是托管主机 Ron.HooksDemo 输出信息可以看到,钩子上安装挂载的顺序执行的

4. 在钩子中加载额外的程序集

我们应该这么理解,钩子程序也是一个普通的应用程序集;所以一个普通的程序集能做到事情,钩子也一样可以

4.1 在 Ron.License 加载一个程序集 Ron.Service,Ron.Service 中定义了一个类 UserService,继承自并实现 IDisposable 接口

    public class UserService : IDisposable    {        public void Dispose()        {            Console.WriteLine("程序集:Ron.Service.dll");            Console.WriteLine("动态加载程序集,执行清理任务已完成");            Console.WriteLine("=========== Ron.Service.dll 结束 ===========");        }    }

4.2 在 Ron.License 的钩子方法中加载 Ron.Service 程序集,创建 IDisposable 的实现,并调用 Dispose() 方法

internal class StartupHook{    public static void Initialize()    {        Console.WriteLine("程序集:Ron.License.dll");        Console.WriteLine("作者:Ron.liang");        Console.WriteLine("博客地址:https://www.cnblogs.com/viter/");        string path = @"C:甥敳獲AdministratorSourceReposRon.HooksDemoRon.ServicebinDebugetcoreapp2.2Ron.Service.dll";        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);        dynamic obj = assembly.CreateInstance("Ron.Service.UserService");        obj.Dispose();        Console.WriteLine("=========== Ron.License.dll 结束 ===========");    }}

4.3 运行程序 Ron.HooksDemo

46d3577de8e6f6a7896ab11bcbf09a42.png

从输出结果看到,Ron.Service 程序集已被成功加载并调用,控制台红色输出信息部分表示加载成功

5. 在 Asp.Net Web Api 项目中使用钩子

Web Api 项目挂载钩子的方式和控制台方式相同,首先我们还是创建一个 Web Api 项目 Ron.HooksDemo.Web接着挂载钩子

  "DOTNET_STARTUP_HOOKS": "C:甥敳獲AdministratorSourceReposRon.HooksDemoRon.InitbinDebugetcoreapp2.2Ron.Init.dll;C:甥敳獲AdministratorSourceReposRon.HooksDemoRon.LicensebinDebugetcoreapp2.2Ron.License.dll"

5.1 运行 Web Api 项目 Ron.HooksDemo.Web

581ecf772e5e813f088dad891a8648e7.png

红色输出部分表示 Web Api 程序的 Main 方法在钩子列表执行完成之后成功启动,这表示在 .Net Core 中,挂载钩子的方式是一致的,其行为也相同

结束语

使用钩子程序注意事项

钩子程序不能依赖于托管主机的TPA列表之外的任何程序集,否则会抛出 FileNotFoundException 的异常不要挂载过多的钩子程序,这可能会出现兼容性问题,如果要使用多个钩子,必须确保每个钩子程序的行为都是独立的,互不干扰的,如果一定要使用,建议修改托管主机的代码,使用依赖注入的方式而不是钩子StartupHook 类应该是 internal 类型的,如果是使用 public 进行修饰,还是可以正常加载钩子程序

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

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

相关文章

3c技能和背包需要改建吗?_认为您需要仪表板? 您应该改建一个笔记本。

3c技能和背包需要改建吗?by Mahdi Karabiben通过Mahdi Karabiben 认为您需要仪表板? 您应该改建一个笔记本。 (Think you need a Dashboard? You should build a Notebook instead.) After first establishing themselves as a key component of the standard Bu…

leetcode 147. 对链表进行插入排序

对链表进行插入排序。 插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的…

JSP过滤器Filter配置过滤类型汇总

一、配置方法1 映射过滤应用程序中所有资源<filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class></filter><filter-mapping> <filter-name>loggerfilter</filt…

ERP流程入门_从会计分录理解企业基本流程[转]

ERP流程入门_从会计分录理解企业基本流程 本贴写给尚未在企业工作过的朋友&#xff01;了解企业的基本流程的一个方法是看它的会计分录,我们现在来看一个完整的企业基本流程&#xff0c;它的会计分录是如何做的&#xff0c;其中有些帐户名称可能不一样&#xff0c;不过没关系&a…

萨默尔机器人_助力产业发展 西安市人工智能机器人学会正式成立

8月23日&#xff0c;西安市人工智能机器人学会在西咸新区沣东新城协同创新港正式成立。西安报业全媒体记者 冯炜 摄8月23日&#xff0c;西安市人工智能机器人学会正式成立。学会将通过市场化机制、社会化服务等方式&#xff0c;整合科技创新资源和人才培养资源&#xff0c;促进…

粒度过粗_这些书帮助我度过了第一次成为技术主管的经历

粒度过粗by Danny Perez丹尼佩雷斯(Danny Perez) 这些书帮助我度过了第一次成为技术主管的经历 (These books helped me navigate my first time being a tech lead) The tech lead was moving to another team for a long-term assignment, and I took over as the engineeri…

随便说说:在ASP.NET应用程序中上传文件

在Web程序中上传文件是很常见的需求。利用HTTP协议上传文件的方式非常有限&#xff0c;最常见的莫过于使用<input type"file" />元素进行上传。这种上传方式会将内容使用multipart/form-data方案进行编码&#xff0c;并将内容POST到服务器端。使用multipart/fo…

leetcode 148. 排序链表(归并排序)

给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 进阶&#xff1a; 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下&#xff0c;对链表进行排序吗&#xff1f; 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1…

理论与哲学就是梳理无限感性经验和知性知识的工具

理论与哲学就是梳理无限感性经验和知性知识的工具&#xff0c; 是因为人脑的特性&#xff0c;或者说人脑功能的局限性而被人创造出来的思想工具。 工具服务于实践&#xff0c;并被实践所检验&#xff08;描述、解释、预见&#xff09;。 工具一旦创建就有其客观性&#xff0c;但…

记一次调用API遇到的问题

调用sonar API 接口&#xff0c;地址如下&#xff1a; http://sonar.*****.com/api/measures/search_history?componenttcmp-devops-service&metricssqale_index%2Cduplicated_lines_density%2Cncloc%2Ccoverage%2Cbugs%2Ccode_smells%2Cvulnerabilities&ps1000 url上…

h5滚动隐藏滚动条_这 10 个值得开启的隐藏功能,让你的 Chrome 释放更多潜力

上次分享了让 Chrome 浏览器用得更顺手的地址栏命令&#xff0c;跟大家整理和介绍了多个 Chrome 地址栏命令&#xff0c;利用好这些命令工具能够提升浏览器配置效率&#xff0c;让你的 Chrome 浏览器用得更顺手。这次介绍的是 Chrome 内置的实验功能&#xff0c;它被单独放在了…

redux ngrx_另一个减少Redux(NGRX)应用程序样板的指南

redux ngrxby Andrey Goncharov通过安德烈贡恰洛夫(Andrey Goncharov) 另一个减少Redux(NGRX)应用程序样板的指南 (Yet another guide to reduce boilerplate in your Redux (NGRX) app) 我们在这里要覆盖什么&#xff1f; (What are we gonna cover here?) In this article,…

leetcode 242. 有效的字母异位词

给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s “anagram”, t “nagaram” 输出: true 示例 2: 输入: s “rat”, t “car” 输出: false 代码 class Solution {public boolean isAnagram(String s, String t) {…

技巧:使用User Control做HTML生成

User Control大家肯定不会陌生&#xff0c;在使用ASP.NET的过程中&#xff0c;除了aspx页面&#xff0c;最常见的就莫过于ascx了。ascx是一个有独立逻辑的组件&#xff0c;提供了强大的复用特性&#xff0c;合理使用&#xff0c;能够大大提高开发效率。通过User Control直接生成…

Spring Boot干货系列:(二)配置文件解析

前言 上一篇介绍了Spring Boot的入门&#xff0c;知道了Spring Boot使用“习惯优于配置”&#xff08;项目中存在大量的配置&#xff0c;此外还内置了一个习惯性的配置&#xff0c;让你无需手动进行配置&#xff09;的理念让你的项目快速运行起来。所以&#xff0c;我们要想把S…

mysql常用操作记录

&#xff08;1&#xff09;判断表中一个字段是空&#xff0c;可为&#xff1a;字段名 IS NULL&#xff08;2&#xff09;类似oracle的decode作用&#xff1a;IF(字段名>0,字段名,0)&#xff08;3&#xff09;时间格式&#xff08;年-月-日&#xff09;&#xff1a;DATE_FORM…

小爱音响调用php接口_阿里API调用二(PHP)

接口地址拼合成功后&#xff0c;用curl函数post获取阿里返回的完整数据&#xff0c;将地址传入getContent()方法中&#xff0c;绝对能获取用户数据。public function getContent($url){$ch curl_init();// 初始化curl_setopt($ch,CURLOPT_URL,$apiprourlall);curl_setopt($ch,…

leetcode 452. 用最少数量的箭引爆气球(贪心算法)

在二维空间中有许多球形的气球。对于每个气球&#xff0c;提供的输入是水平方向上&#xff0c;气球直径的开始和结束坐标。由于它是水平的&#xff0c;所以纵坐标并不重要&#xff0c;因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。 一支弓箭可以沿着 x…

javascript编程题_如何开始使用JavaScript进行竞争性编程

javascript编程题by Priyabrata Biswas通过Priyabrata Biswas 如何开始使用JavaScript进行竞争性编程 (How to get started with Competitive Programming in JavaScript) If you’re not familiar with competitive programming, basically it is a mind sport with the aim …

hibernate Criteria(条件查询接口)

Criteria&#xff08;条件查询接口&#xff09; // 1.简单查询 List<Customer> list session.createCriteria(Customer.class).list();// 2.条件查询: Criteria criteria session.createCriteria(Customer.class); criteria.add(Restrictions.eq("name",&quo…