Natasha 4.0 探索之路系列(二) 「域」与插件

700406303057a863257f57a08de2cb3d.png

域与ALC

在 Natasha 发布之后有不少小伙伴跑过来问域相关的问题,能不能兼容 AppDomain、如何使用 AppDomain、为什么 CoreAPI 阉割了 AppDomain 等一系列的问题。

今天答复一下:

  • 首先 AppDomain 作为程序集隔离容器的存在,是风靡了 .NET Framework 的各大版本,被誉为是轻量级进程,由 AppDomain 发展的特性和操作也很多。而 Natasha 采用的是 AssemblyLoadContext 简称 "ALC";ALC 是 .NET Core 版本后出现的操作类,这个类在 .NET Core 及以后的版本中,只要加载依赖项,就会调用它。有趣的是,你在调试代码过程中如果去观察它,可以看到它缓存程序集的数量在增加。因为还没运行到的程序集可以先不加载,检测代码 AssemblyLoadContext.Default.Assemblies.Count()

  • 其次它本不是域,或者不能称为域。它和域的区别是,FW 支持多域,而 CORE 仅支持单域,CORE 就一个默认域。ALC 的名字翻译过来是,程序集加载上下文,看英文名字也是和域区分开了;

  • 最后一点区别是域的卸载是强制的,ALC 的卸载是“协商”的,相比域而言,ALC 中的程序集所包含的元数据被保持引用,就不能被卸载,比如你反射出来的类或者方法或者其他什么的放到了一个主域的字典中,那么字典不毁,这个 ALC 就没办法卸载,尽管 ALC 有 Unload 方法,卸载还是要看元数据是否被保持引用;

Natasha 设计初衷是使用隔离性较强的字眼,用域的概念来减少 .NET Core 带来的新的理解成本,另外之前有打算兼容 AppDomain 的想法。

这个想法的优先级不高:

  1. 是 .NET Core 是在 3.0 时出现比较明显的分水岭,包括依赖解析,上下文域识别等重要特性的支持;

  2. 是 Roslyn 对 FW 的支持不能低于(4.6.1);

  3. 是 UT测试需要区分版本来做,很麻烦,插件部分的测试不简单;

  4. 是 个人精力原因,还要工作,还要维护其他项目;

这里也希望公司们都能平稳度过升级期,早点迎接更好更实用的"未来技术"。

Natasha 域的使用

插件的开发技巧

这里不得不回顾一下插件开发的知识,它可不是像培训机构讲的编译一个 DLL 然后 Assembly.LoadFrom 就可以的。首先要了解加载插件的两个侧重点,插件依赖打包和插件依赖管理。

  • 插件依赖打包:首先插件生成时,你需要把必要的引用库一起打包,此时需要在工程文件的 PropertyGroup 节点中添加 <EnableDynamicLoading>true</EnableDynamicLoading> 让编译程序输出依赖文件,同时不要忘了交付 "xxx.deps.json",这是让宿主程序解析依赖的关键;

  • 插件依赖管理:如果你的接口 IPlugin 给到插件开发人员,让他按照这个接口去写功能,那么当他交付插件时,你不能再将他包里的 IPlugin 再引进来。否则如下代码将报错,(var plugin = (IPlugin)Activtor.Create(pluginA);) 类型转换错误,原因是代码中的 IPlugin 在主域中使用,而 pluginA 是加载到其他域中的,而且在那个域里也存在一个 IPlugin,这个接口类型不同于主域的接口类型,因此在转换时会引发类型转换的错误。

  • 解决方法1:让插件开发人员在自己的工程添加设置,自动排除这个主要依赖(官方的推荐做法):

<ItemGroup><ProjectReference Include="..\IPlugin\IPlugin.csproj"><Private>false</Private><ExcludeAssets>runtime</ExcludeAssets></ProjectReference></ItemGroup>
  • 解决方法2:在实现的 ALC 中添加过滤方法排除 IPlugin

以上是基本的插件开发知识,如果你还不了解,可以读一读微软插件开发文档。

https://docs.microsoft.com/zh-cn/dotnet/core/tutorials/creating-app-with-plugin-support

单独使用 NatashaDomain :

  1. 引入包 DotNetCore.Natasha.Domain 包。

  2. 加载插件

NatashaDomain domain = new NatashaDomain("NewPluginDomain");//加载方法: 参数1: 插件位置;参数2: 根据 AssemblyName 排除需要加载的插件名称。//加载插件,如果主域存在相同名字的依赖,则使用版本较高的那版。domain.LoadPluginWithHighDependency("c:/xxx/pluginA.dll", excludeAssembliesFunc: asn => asn.Name.Contains("IPlugin"));//加载插件,如果主域存在相同名字的依赖,则使用版本较低的那版。domain.LoadPluginWithLowDependency("c:/xxx/pluginA.dll", excludeAssembliesFunc: asn => asn.Name.Contains("IPlugin"));//加载插件,如果主域存在相同名字的依赖,则使用主域中的那版。domain.LoadPluginUseDefaultDependency("c:/xxx/pluginA.dll");//加载插件,不判重,全部加载。domain.LoadPluginWithAllDependency("c:/xxx/pluginA.dll", excludeAssembliesFunc: asn => asn.Name.Contains("IPlugin"));//卸载域domain.Dispose();

避坑指南

如果您使用以上 API 将插件加载到同一个域,会出现很多问题:7bb744a348e384227bb5ec6e08782a92.png

建议:

  1. 写插件时,本身解决好引用管理问题;

  2. 如果插件过于庞大,请将插件功能解耦,并加载到不同域中反射给主域执行;

  3. 主域要对依赖使用版本检查,请在插件加载代码之前执行一些功能。比如 _ = typeof(Dapper.CommandDefinition); 尽管这句没有用,但它将迫使运行时将 Dapper 的程序集加载到默认上下文的缓存中,这样在你加载插件时,如果遇到 Dapper 依赖,将触发版本检查详见代码。https://github.com/dotnetcore/Natasha/blob/main/samples/PluginSample/PluginSample/Program.cs#L145

结尾

您可以自行查看案例代码。NatashaDomain 是 Natasha 动态编译的父级,Natasha 动态编译中的 NatashaReferenceDomain 继承了此类,因此如果您想使用 Natasha 进行动态构建请使用 NatashaReferenceDomain。下一篇将讲解 Natasha 的基本编译知识。

98b27b6b1595ac496a02d08cd7130e69.png

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

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

相关文章

cake fork什么意思_Java7任务并行执行神器:Forkamp;Join框架

Fork/Join是什么&#xff1f;Fork/Join框架是Java7提供的并行执行任务框架&#xff0c;思想是将大任务分解成小任务&#xff0c;然后小任务又可以继续分解&#xff0c;然后每个小任务分别计算出结果再合并起来&#xff0c;最后将汇总的结果作为大任务结果。其思想和MapReduce的…

linux C语言之called object ‘maze’ is not a function or function pointer printf(“%d\t“, maze(i, j))

今天写广度优先搜索的时候出现了这个问题&#xff0c; 解决办法&#xff1a; 特么我傻逼了&#xff0c;明显是数组&#xff0c;我写成了mate(i, j),然后我改了写成了mate[i, j]; 特么我又傻逼了 改成mate[i][j] 就可以了

Greenplum 数据库架构分析

Greenplum 数据库是最先进的分布式开源数据库技术&#xff0c;主要用来处理大规模的数据分析任务&#xff0c;包括数据仓库、商务智能&#xff08;OLAP&#xff09;和数据挖掘等。自2015年10月正式开源以来&#xff0c;受到国内外业内人士的广泛关注。本文就社区关心的Greenplu…

Blog.Core高级进阶:共赴五年之约

读书破万卷&#xff0c;下笔如有神。佳著荐大家马上新年好呀&#xff0c;还有七天就是春节了&#xff0c;2022年是真真正正的到来了&#xff0c;老张打算在新的一年里&#xff0c;继续为开源社区做贡献&#xff0c;Blog.Core开源项目也正式进入第五个年头了&#xff0c;是时候作…

stringredistemplate设置过期时间_Redis的过期删除策略和内存淘汰机制

Redis的key可以设置过期时间&#xff0c;那是否意味着时间一到就会马上被删除呢&#xff1f;Redis的数据存储大小是有限的&#xff0c;假如内存不足Redis有什么应对策略呢&#xff1f;本篇文章将介绍一下Redis的过期策略和内存淘汰机制。1、redis的过期策略1.定时删除在设置key…

linux之怎么使vim永久显示行号

1、进入当前用户目录 2、输入下面命令 vim ~/.vimrc 3、退出保存 :x 4、用vim打开文件验证

java.util.ConcurrentModificationException异常

2019独角兽企业重金招聘Python工程师标准>>> <p> 今天遇到了一个小bug&#xff0c;在对ArrayList操作时出现了java.util.ConcurrentModificationException异常。原来是arrary在遍历时&#xff0c;是不能删除其中的对象的。 for(MediaFeedData item : Item…

eclipse中git插件配置 编辑

一、Eclipse上安装GIT插件EGit EGit插件地址&#xff1a;http://download.eclipse.org/egit/updates OK&#xff0c;随后连续下一步默认安装就可以&#xff0c;安装后进行重启Eclipse 二、在Eclipse中配置EGit 准备工作&#xff1a;需要在https://github.com 上注册账号 Prefer…

使用 C# 开发 Kubernetes 组件,获取集群资源信息

写什么呢前段时间使用 C# 写了个项目&#xff0c;使用 Kubernetes API Server&#xff0c;获取信息以及监控 Kubernetes 资源&#xff0c;然后结合 Neting 做 API 网关。体验地址 http://neting.whuanle.cn:30080/账号 admin&#xff0c;密码 admin123本篇文章主要介绍&#xf…

whitelabel error page什么意思_什么是RESTful API?总算能说清楚了

要弄清楚什么是RESTful API,首先要弄清楚什么是REST。REST -- REpresentational State Transfer&#xff0c;英语的直译就是“表现层状态转移”。如果看这个概念&#xff0c;估计没几个人能明白是什么意思。那下面就让我来用一句人话解释一下什么是RESTful:URL定位资源&#xf…

【转】Asp.net控件开发学习笔记整理篇 - 数据回传

最近一直在做MVC项目&#xff0c;对于WEBFORM 好像快忘记了。周末无聊&#xff0c;顺带看看他人的笔记。再次温习下。 复习大纲&#xff1a; 导航、页面生命周期及其它导论 一、服务器控件生命周期 二、控件开发基础 三、Asp.net服务端状态管理 四、Asp.net客户端状态管理 五、…

BZOJ2326 [HNOI2011]数学作业

首先&#xff0c;列方程 我们定义s[i] 10 ^ ((int) log(i)) 于是&#xff0c;f[i] (f[i - 1] * s[i] i) % p 反正总之就是个沙茶递推 然后我们来看优化。。。怎么感觉像矩阵乘法呢&#xff1f; 发现要按照log(i)即i的位数分类讨论&#xff0c;在相同位数的时候令矩阵为 s[i]…

简直不敢相信!这个史上最被低估的学科,看完竟瑟瑟发抖!

▲ 点击查看历史&#xff0c;无疑是大众参与度较高的知识性学科之一&#xff0c;既没有艰深的原理和公式&#xff0c;也不需要较高的欣赏能力。不仅门槛低&#xff0c;而且具有故事性&#xff0c;容易形成话题&#xff0c;茶余饭后&#xff0c;几乎每个人、每个孩子都能谈论几句…

一款强大的Kubernetes API流量查看神器

点击上方蓝字关注 &#x1f446;&#x1f446;大家好&#xff0c;我是小碗汤&#xff0c;今天分享一个k8s流量查看器~mizu。mizu 是为 Kubernetes 提供的一个简单而强大的 API 流量查看器&#xff0c;可以查看微服务之间的所有 API 通信&#xff0c;以帮助调试和排除故障。相当…

辉光UIView的category

辉光UIView的category 本人视频教程系类 iOS中CALayer的使用 效果如下&#xff1a; 源码&#xff1a; UIViewGlowView.h 与 UIViewGlowView.m // // UIViewGlowView.h // YouXianClock // // Created by YouXianMing on 14-12-21. // Copyright (c) 2014年 YouXianMing. …

javascript 动态创建表格

<html><head><script>function createTable(rows,lines){this.rowsrows;this.lineslines;var Bodydocument.getElementById(body);var Tabledocument.createElement(table);//创建table标签元素Table.setAttribute(border,1);//给table标签添加其他属性for(v…

linux c之加入了加入原文件 math.h调用abs()函数出现implicit declaration of function错误

今天在vim 写C语言的时候 代码我已经导入了#include<math.h> 但是当我调用ads()函数的时候出现了下面错误 解决办法&#xff1a; 把abs函数改写成fabs函数就行&#xff0c;然后去网上找原因&#xff0c;发现fabs是求浮点数的&#xff0c;ads求整形的&#xff0c;以后在…

你的女神今日结婚了!!!你失恋了......

1 新垣结衣结了婚▼2 我和朋友最近的聊天内容&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 白粥盖浇饭&#xff1f;&#xff1f;&#xff1f;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 中国人的辈分可以复杂到什么程度&#xff1f;&#xff08…