首页 > 解决方案 > netcore 3.1 中的 AssemblyLoadContext.Default 解析插件类型,但当插件使用传递依赖时无法执行其实例

问题描述

我在 netcoreapp3.1 中有一个使用 netstandard2.0 插件的控制台应用程序。该插件引用一个类库并实现一个接口所有dll依赖项都在插件文件夹中,plugin.dep.json包含所有引用的库。

当我运行时:

AssemblyLoadContext.Default.LoadFromAssemblyPath("path/to/main_myplugin.dll");//load plugin

它解析接口的类型

当我尝试运行下面给出的实例时,它失败了:

 if (type != null)  //type is resolved and not null
            {
                var instance = (IContract)Activator.CreateInstance(type); //instance is created
                Console.WriteLine($"Create instance  : {instance.GetType()}"); // ok instance is created
                var ret = instance.Execute(); //!!!fire exception here
                Console.WriteLine(ret);
            }

并触发错误消息:

System.IO.FileNotFoundException:'无法加载文件或程序集'MyLibObjectsLib,版本 = 1.0.0.0,文化 = 中性,PublicKeyToken = null'。该系统找不到指定的文件。'

如果我加载了所有依赖项,它工作正常。

使用 AssemblyLoadContext.Default 时应该加载所有依赖项还是一个错误?

标签: c#plugins.net-coreassembly-loading

解决方案


我在dotnet项目中问过这个问题

所有功劳归@vitek-karas

详细的答案是:

目前这是设计使然。LoadFromAssemblyPath 以及任何其他类似 LoadAssembly 的方法只会加载该程序集,它们不会尝试加载“插件”。对于这种情况,您需要 AssemblyDependencyResolver 并将其连接到默认 ALC(可能通过 Resolving 事件),并希望主机应用程序和插件之间没有冲突(因为它们将共享所有依赖项)等等上。通常这就是为什么最好将插件加载到他们自己的 ALC 中,因为这会创建必要的隔离,并且还可以轻松连接 AssemblyDependencyResolver。

更高级别的答案 - 在 3.0 中,我们没有尝试提供“插件加载”API,因为在它应该如何表现方面存在太多悬而未决的问题(确切的隔离行为很难正确处理,因此它适用于大多数人用例)。相反,我们提供了必要的构建块(ALC、ADR、diag 改进......)并依靠用户编写 cca 20 行代码来实现自定义 ALC。在 5.0 中,我们通过在整个程序集绑定过程中添加详细跟踪来改进诊断,这通常有助于在加载程序集时调试问题,特别是在实现自定义 ALC 时。


推荐阅读