当前位置: 首页 > news >正文

.NET Core 中插件式开发实现

在 .NET Framework 中,通过AppDomain实现动态加载和卸载程序集的效果;但是.NET Core 仅支持单个默认应用域,那么在.NET Core中如何实现【插件式】开发呢?

一、.NET Core 中 AssemblyLoadContext的使用

1、AssemblyLoadContext简介:

每个 .NET Core 应用程序均隐式使用 AssemblyLoadContext。它是运行时的提供程序,用于定位和加载依赖项。只要加载了依赖项,就会调用 AssemblyLoadContext 实例来定位该依赖项。

  • 它提供定位、加载和缓存托管程序集和其他依赖项的服务。

  • 为了支持动态代码加载和卸载,它创建了一个独立上下文,用于在其自己的 AssemblyLoadContext 实例中加载代码及其依赖项。

2、AssemblyLoadContext和AppDomain卸载差异:

使用 AssemblyLoadContext 和使用 AppDomain 进行卸载之间存在一个值得注意的差异。对于 Appdomain,卸载为强制执行。

卸载时,会中止目标 AppDomain 中运行的所有线程,会销毁目标 AppDomain 中创建的托管 COM 对象,等等。对于 AssemblyLoadContext,卸载是“协作式的”。

调用 AssemblyLoadContext.Unload 方法只是为了启动卸载。以下目标达成后,卸载完成:

1、没有线程将程序集中的方法加载到其调用堆栈上的 AssemblyLoadContext 中。

2、程序集中的任何类型都不会加载到 AssemblyLoadContext,这些类型的实例本身由以下引用:

    • AssemblyLoadContext 外部的引用,弱引用(WeakReference 或 WeakReference)除外。

    • AssemblyLoadContext 内部和外部的强垃圾回收器 (GC) 句柄(GCHandleType.Normal 或 GCHandleType.Pinned)。

二、.NET Core 插件式方式实现

1、创建可卸载的上下文PluginAssemblyLoadContext

class PluginAssemblyLoadContext : AssemblyLoadContext
{private AssemblyDependencyResolver _resolver;/// <summary>/// 构造函数/// isCollectible: true 重点,允许Unload/// </summary>/// <param name=pluginPath></param>public PluginAssemblyLoadContext(string pluginPath) : base(isCollectible: true){_resolver = new AssemblyDependencyResolver(pluginPath);}protected override Assembly Load(AssemblyName assemblyName){string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);if (assemblyPath != null){return LoadFromAssemblyPath(assemblyPath);}return null;}protected override IntPtr LoadUnmanagedDll(string unmanagedDllName){string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);if (libraryPath != null){return LoadUnmanagedDllFromPath(libraryPath);}return IntPtr.Zero;}
}

2、创建插件接口及实现

整体项目结构为:

图片

a)添加项目PluginInterface,插件接口:

public interface IPlugin
{string Name { get; }string Description { get; }string Execute(object inPars);
}

b)添加HelloPlugin项目,实现不引用外部dll插件

public class HelloPlugin : PluginInterface.IPlugin
{public string Name => "HelloPlugin";public string Description { get => "Displays hello message."; }public string Execute(object inPars){return ("Hello !!!" + inPars?.ToString());    } }

c)添加JsonPlugin项目,实现引用三方dll插件

public class JsonPlugin : PluginInterface.IPlugin
{public string Name => "JsonPlugin";public string Description => "Outputs JSON value.";private struct Info{public string JsonVersion;public string JsonLocation;public string Machine;public DateTime Date;}public string Execute(object inPars){Assembly jsonAssembly = typeof(JsonConvert).Assembly;Info info = new Info(){JsonVersion = jsonAssembly.FullName,JsonLocation = jsonAssembly.Location,Machine = Environment.MachineName,Date = DateTime.Now};return JsonConvert.SerializeObject(info, Formatting.Indented);}
}

d)添加PluginsApp项目,实现调用插件方法:

修改窗体界面布局:

图片

添加执行方法

/// <summary>
/// 将此方法标记为noinline很重要,否则JIT可能会决定将其内联到Main方法中。
/// 这可能会阻止成功卸载插件,因为某些实例的生存期可能会延长到预期卸载插件的时间点之外。
/// </summary>
/// <param name="assemblyPath"></param>
/// <param name="inPars"></param>
/// <param name="alcWeakRef"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.NoInlining)]
static string ExecuteAndUnload(string assemblyPath, object inPars, out WeakReference alcWeakRef)
{string resultString = string.Empty;// 创建 PluginLoadContext对象var alc = new PluginAssemblyLoadContext(assemblyPath);//创建一个对AssemblyLoadContext的弱引用,允许我们检测卸载何时完成alcWeakRef = new WeakReference(alc);// 加载程序到上下文// 注意:路径必须为绝对路径.Assembly assembly = alc.LoadFromAssemblyPath(assemblyPath);//创建插件对象并调用foreach (Type type in assembly.GetTypes()){if (typeof(IPlugin).IsAssignableFrom(type)){IPlugin result = Activator.CreateInstance(type) as IPlugin;if (result != null){resultString = result.Execute(inPars);break;}}}//卸载程序集上下文alc.Unload();return resultString;
}

三、效果验证

1、非引用外部dll的插件执行:执行后对应dll成功卸载,程序集数量未增加。

图片


2、引用外部包的插件:执行后对应dll未卸载,程序集数量增加。

图片


通过监视查看对象状态:该上下文在卸载中。暂未找到原因卸载失败(疑问?)

图片

四、总结

虽然微软文档说.NET Core中使用AssemblyLoadContext来实现程序集的加载及卸载实现,但通过验证在加载引用外部dll后,加载后不能正常卸载。或者使用方式还不正确。

源码地址:https://github.com/cwsheng/PluginsApp

相关文章:

.NET Core 中插件式开发实现

在 .NET Framework 中&#xff0c;通过AppDomain实现动态加载和卸载程序集的效果&#xff1b;但是.NET Core 仅支持单个默认应用域&#xff0c;那么在.NET Core中如何实现【插件式】开发呢&#xff1f; 一、.NET Core 中 AssemblyLoadContext的使用 1、AssemblyLoadContext简…...

并查集模版以及两道例题

&#x1f4af; 博客内容&#xff1a;并查集 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准C后端工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&#xff1a;这里是C…...

英飞凌TLF35584规格书中文

官网&#xff1a; 英飞凌TLF35584QVVS2 TLF35584_SPI&#xff1a; 1 Overview2 Block Diagram3 Pin Configuration3.1 Pin Assignment - PG-VQFN-48 4 General Product Characteristics4.1 Absolute Maximum Ratings 绝对最大额定值4.2 Functional Range4.3 Thermal Resistance…...

【教3妹学编程-算法题】最大单词长度乘积

3妹&#xff1a;哇&#xff0c;今天好冷啊&#xff0c; 不想上班。 2哥&#xff1a;今天气温比昨天低8度&#xff0c;3妹要空厚一点啊。 3妹 : 嗯&#xff0c; 赶紧把我的羽绒服找出来穿上&#xff01; 2哥&#xff1a;哈哈&#xff0c;那倒还不至于&#xff0c; 不过气温骤降&…...

遇到python程序是通过sh文件启动的,如何调试

说明 下载的源码总会遇到这样启动的&#xff1a; 并且发现shell文件内容很多&#xff0c;比较复杂&#xff0c;比如&#xff1a; 解决方案 这时候想要调试&#xff0c;可以通过端口连接的方式调试&#xff0c;具体方法如下&#xff1a; 在vscode调试按钮中添加远程附加调试…...

应用系统集成-Spring Integration

应用系统集成-Spring Integration 图1 EIP 消息系统模式全景图。 Spring Integration 是系统集成的一个实现框架&#xff0c;提供了对EIP核心概念&#xff1a;Endpoint、Message、Channel、Router、Translator的抽象及相关框架实现&#xff0c;使得基于Spring Integration进行…...

亚马逊与TEMU平台欧代英代如何注册?注册欧代/英代流程及注意事项

亚马逊与TEMU平台欧代英代如何注册&#xff1f;注册欧代/英代流程及注意事项 亚马逊平台的商家的产品&#xff0c;由于受到欧盟商品安全新法规市场监管法规欧盟要求所有标有CE标志的商品&#xff0c;都要拥有欧盟境内的欧代作为商品合规的联系方式(也称为负责人)。由于英国脱离…...

【嵌入式开发工具】STM32+Keil实现软件工程搭建与开发调试

本篇文章介绍了使用Keil来对STM32F103C8芯片进行初始工程搭建&#xff0c;以及开发与工程调试的完整过程&#xff0c;帮助读者能够在实战中体会到Keil这个开发环境的使用方法&#xff0c;了解一个嵌入式工程从无到有的过程&#xff0c;并且具备快速搭建一个全新芯片对应最小软件…...

python 去除图像中的框

最近在做图像标注&#xff0c;会出现以下的图片&#xff0c;需要去除其中的边框。 1.思路 人工标注画框的范围P&#xff0c;并使用标注工具在画框上画一个点A。获取点A的坐标和颜色。在范围P内&#xff0c;将与点A颜色相似的每一个点x的颜色&#xff0c;替换为点x上下&#…...

企业邀约媒体的方式方法?-(快速精准)

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 快速而精确地邀约媒体通常需要有计划和策略性的方法。以下是一些方法&#xff0c;可以帮助企业有效地邀请媒体&#xff1a; 1. 媒体列表构建&#xff1a;首先&#xff0c;建立一个精心筛…...

旅游业为什么要选择VR全景,VR全景在景区旅游上有哪些应用

引言&#xff1a; VR全景技术的引入为旅游业带来了一场变革。这项先进技术不仅提供了前所未有的互动体验&#xff0c;还为景区旅游文化注入了新的生机。 一&#xff0e;VR全景技术&#xff1a;革新旅游体验 1.什么是VR全景技术&#xff1f; VR全景技术是一种虚拟现实技术&am…...

搭建第一个区块链网络与一键部署WeBASE步骤

官网 搭建第一个区块链网络 — FISCO BCOS v2 v2.9.0 文档 (fisco-bcos-documentation.readthedocs.io) 一键部署 — WeBASE v1.5.5 文档 (webasedoc.readthedocs.io) 步骤 默认如MySQL、Python、java等依赖已经引入 1.创建操作目录, 下载安装脚本 创建操作目录 cd ~ &a…...

MTK联发科、高通、紫光展锐手机SOC平台型号汇总(含详细参数)

MediaTek联发科手机平台汇总&#xff1a; Qualcomm高通SOC平台汇总&#xff1a; 紫光展锐SOC平台汇总&#xff1a; 新移科技已成功研发手机SOC平台&#xff1a; 联发科平台&#xff1a; MTK6739、MTK6761、MTK6762、MTK6765、MTK8788、MTK6853、MTK6873、MTK6833、MTK6877、…...

【ARM AMBA AXI 入门 12 -- AXI协议中的 WLAST 与 RLAST】

文章目录 AXI协议中的 WLAST 与 RLAST AXI协议中的 WLAST 与 RLAST AMBA AXI协议是由ARM公司定义的一种高性能&#xff0c;高频率的总线协议。总线协议中的 WLAST 信号是一个重要的信号&#xff0c;它在 AXI 协议中用来标识一个突发&#xff08;Burst&#xff09;传输的最后一…...

11.6 知识总结(筛选器方法、操作标签、事件)

一、 筛选器方法 document.getElementById()------>标签对象------------>直接就是标签 $(document.getElementById()) -------> jQuery对象-------->可以使用jQuery提供的方法 jQuery(document.getElementById()) -------> jQuery对象-------->可以使用jQue…...

Devchat插件:AI智能编程助手,让你告别脏活累活。

文章目录 前言注册登录DevChat的安装和配置DevChat插件安装DevChat插件配置 DevChat的简单使用后记 前言 随着人工智能技术的不断发展和普及&#xff0c;它正在深刻影响着各行各业&#xff0c;并逐渐成为改变世界的重要力量。在软件开发领域&#xff0c;人工智能技术也给开发者…...

0-1矩阵列互斥问题——回溯法 Python实现

三、 0-1 矩阵的列集互斥问题。给定一个 m n m \times n mn 的 0-1 矩阵 A \mathrm{A} A 。定义列互斥为: 对于矩阵 A A A 中的任意两列 i i i 和 j j j, 如果在对应的每一行上, i i i 和 j j j 不存在同时为 1 的情况, 则称列 i \mathrm{i} i 和 j \mathrm{j} j 互斥…...

wandb 安装本地部署使用教程

1、官网注册 wandb.ai是一个为机器学习开发者提供的开发工具平台&#xff0c;可以帮助用户跟踪实验&#xff0c;管理和版本数据&#xff0c;以及与团队协作&#xff0c;从而更专注于构建最佳模型。 wandb官网&#xff1a; https://wandb.ai 首先我们打开官网注册号自己的账号并…...

飞桨平台搭建PP-YOLOE模型

一、创建项目 此博客仅是运行PP-YOLOE源码&#xff0c;这里以变压器渗漏数据集为例COCO数据集太大了&#xff0c;跑不动&#xff0c;V100训练预估计得7天左右&#xff0c;即便是A100也得4天半&#xff0c;变压器渗漏油数据集跑一个小时左右&#xff0c;还可以接受&#xff0c;…...

Js重点内容

一&#xff0c;什么是js javascript是运行在客户端&#xff08;浏览器&#xff0c;可预览&#xff09;的编程语言 二&#xff0c;主要的功能 用来给静态页&#xff08;html网页&#xff09;增加一些动态功能&#xff08;比如轮播图、tab切换&#xff09; 三&#xff0c;应用…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...