AssemblyLoadContext.Default net core 3.1 解决插件类型在插件使用传递依赖时无法执行其实例的问题
AssemblyLoadContext.Default in netcore 3.1 resolve the plugin type but can't excute its instance when the plugin use transitive dependency
我在 netcoreapp3.1 中有一个使用 netstandard2.0 插件的控制台应用程序。
该插件引用了一个 class 库并实现了一个接口
所有 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: 'Could not load file or assembly 'MyLibObjectsLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.'
如果我加载了所有依赖项,它工作正常。
我应该在使用 AssemblyLoadContext.Default 时加载所有依赖项还是一个错误?
我在dotnet项目中问过这个问题
所有功劳归@vitek-karas。
详细答案是:
Currently this is by design. LoadFromAssemblyPath as well as any other LoadAssembly-like methods only ever load that assembly, they don't try to load a "plugin". For this case to work you would need the AssemblyDependencyResolver and hook it up to the Default ALC (probably via the Resolving event), and hope that there are no collisions between the host app and the plugin (since they will share all dependencies) and so on. Generally this is why it's better to load plugins into their own ALCs as that creates the necessary isolation and also makes it easy to hook up AssemblyDependencyResolver.
Higher-level answer - in 3.0 we didn't try to provide a "plugin load" API as there were too many open questions in how it should behave (the exact isolation behavior is very tricky to get right so that it would work for most use cases). Instead we provided the necessary building blocks (ALC, ADR, diag improvements, ...) and rely on users to write the cca 20 lines of code to implement the custom ALC. In 5.0 we are improving diagnostics by adding detailed tracing around the entire assembly binding process, that should help debugging issues when loading assemblies in general, but specifically when implementing custom ALCs.
我在 netcoreapp3.1 中有一个使用 netstandard2.0 插件的控制台应用程序。 该插件引用了一个 class 库并实现了一个接口 所有 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: 'Could not load file or assembly 'MyLibObjectsLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.'
如果我加载了所有依赖项,它工作正常。
我应该在使用 AssemblyLoadContext.Default 时加载所有依赖项还是一个错误?
我在dotnet项目中问过这个问题
所有功劳归@vitek-karas。
详细答案是:
Currently this is by design. LoadFromAssemblyPath as well as any other LoadAssembly-like methods only ever load that assembly, they don't try to load a "plugin". For this case to work you would need the AssemblyDependencyResolver and hook it up to the Default ALC (probably via the Resolving event), and hope that there are no collisions between the host app and the plugin (since they will share all dependencies) and so on. Generally this is why it's better to load plugins into their own ALCs as that creates the necessary isolation and also makes it easy to hook up AssemblyDependencyResolver.
Higher-level answer - in 3.0 we didn't try to provide a "plugin load" API as there were too many open questions in how it should behave (the exact isolation behavior is very tricky to get right so that it would work for most use cases). Instead we provided the necessary building blocks (ALC, ADR, diag improvements, ...) and rely on users to write the cca 20 lines of code to implement the custom ALC. In 5.0 we are improving diagnostics by adding detailed tracing around the entire assembly binding process, that should help debugging issues when loading assemblies in general, but specifically when implementing custom ALCs.