C# 使用Json.NET序列化后卸载程序集

C# 使用Json.NET序列化后卸载程序集,c#,json.net,.net-core-3.0,C#,Json.net,.net Core 3.0,我们需要卸载我们软件的插件。插件加载到单独的AssemblyLoadContext(.net core 3.0)中,并通过序列化数据与主软件通信。如果使用Json.NET进行序列化,则永远不会释放对已序列化对象类型的引用;如果此类型是在插件中定义的,则永远不会卸载AssemblyLoadContext 我们用复杂的反射魔法实现了插件卸载——在System.ComponentModel.TypeConverter程序集中进行了一些手动缓存清理,但这看起来像是一个肮脏的黑客 另一种选择是在插件中包含

我们需要卸载我们软件的插件。插件加载到单独的AssemblyLoadContext(.net core 3.0)中,并通过序列化数据与主软件通信。如果使用Json.NET进行序列化,则永远不会释放对已序列化对象类型的引用;如果此类型是在插件中定义的,则永远不会卸载AssemblyLoadContext

我们用复杂的反射魔法实现了插件卸载——在System.ComponentModel.TypeConverter程序集中进行了一些手动缓存清理,但这看起来像是一个肮脏的黑客

另一种选择是在插件中包含Newtonsoft.Json,并在单独的上下文中加载它。尽管不仅Newtonsoft.Json.dll,甚至System.ComponentModel.TypeConverter.dll都在单独的上下文中加载,但这并没有帮助。缓存仍在默认上下文中填充

有人知道吗,在用Json.NET序列化插件类型之后,有没有一种卸载插件的好方法


非常感谢

卸载插件的AssemblyLoadContext后,是否正确清除了弱引用

请查看以下文档:

但是,卸载不会立即完成。如前所述,它依赖垃圾收集器从测试程序集中收集所有对象。在许多情况下,无需等待卸载完成。但是,在某些情况下,知道卸载已经完成是很有用的。例如,您可能希望从磁盘删除加载到自定义AssemblyLoadContext中的程序集文件。在这种情况下,可以使用以下代码段。它触发垃圾收集,并在循环中等待挂起的终结器,直到对自定义AssemblyLoadContext的弱引用设置为null,表示已收集目标对象。在大多数情况下,只需要一次循环。但是,对于在AssemblyLoadContext中运行的代码创建的对象具有终结器的更复杂的情况,可能需要更多的过程

执行逻辑,卸载并获取弱引用:

WeakReference testAlcWeakRef;
int result = ExecuteAndUnload("absolute/path/to/your/assembly", out testAlcWeakRef);
运行垃圾收集并等待弱引用的终结器处于活动状态。如果需要,可重复多达10次:

for (int i = 0; testAlcWeakRef.IsAlive && (i < 10); i++)
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
}
for(int i=0;testAlcWeakRef.IsAlive&&(i<10);i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
再看看这条线,它看起来与您描述的非常相似:

for (int i = 0; testAlcWeakRef.IsAlive && (i < 10); i++)
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
}