将程序集加载到新的AssemblyLoadContext时,方法没有实现

问题描述:

我正在尝试创建一个带有插件的简单应用程序,每个插件都加载到单独的AssemblyLoadContext中,但是当我尝试调用插件程序集的方法GetExportedTypes()时,我会得到类型为'T'的 TypeLoadException'方法'M''来自程序集'A'的没有实现" .
没有实现的方法来自从通用接口继承的类,而接口又位于应用程序和插件之间共享的程序集中.
如果我使用AssemblyLoadContext.Default加载所有插件程序集,则默认一切正常,并且没有错误.
另一个有趣的事实是,错误仅在插件引用 Microsoft.EntityFrameworkCore.SqlServer 时发生共享接口程序集不存在于plugin文件夹中,而是位于本地nuget源中,因此没有版本不匹配

I am trying to create a simple app with plugins with each plugin loading into a separate AssemblyLoadContext, but when i try to call method GetExportedTypes() of plugin assembly i get TypeLoadException 'Method 'M' in type 'T' from assembly 'A' does not have an implementation'.
Method that does not have implementation comes from class that inherits from an common interface, interface in turn is in an assembly that is shared between app and plugin.
If i load all plugin assemblies with AssemblyLoadContext.Default everything works fine and there is no error.
The other fun fact is that error only happens when plugin refereces Microsoft.EntityFrameworkCore.SqlServer The shared interface assembly is not present in plugin folder and is in a local nuget source, so ther is no version mismatch

感谢您的帮助.

谢谢

我也遇到了这个问题.在我的情况下,插件dll引用了Default AssemblyLoadContext和我的插件AssemblyLoadContext都使用的另一个dll.一旦我在插件的csproj中明确设置了

I have had this problem too. In my case, the plugin dll was referencing another dll that was used by both Default AssemblyLoadContext and my plugin AssemblyLoadContext. Once I have explicitly set in the csproj of my plugin the

<Private>true</Private>
<ExcludeAssets>runtime</ExcludeAssets>

对于这两个共享程序集,一切都像超级按钮一样工作.

for both the shared assemblies, everything worked like a charm.

希望它也对您有帮助.

否则,更通用的解决方案可能是进入插件的自定义AssemblyLoadContext并按如下所示编写Load方法

Otherwise, a more generic solution might be to go into your plugin's custom AssemblyLoadContext and write the Load method as follows

protected override Assembly Load(AssemblyName assemblyName)
    {
        // This will fallback to loading the assembly from default context.
        if (AssemblyLoadContext.Default.Assemblies.Any(a=> a.FullName == assemblyName.FullName))
            return null;

        string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
        if (assemblyPath != null)
        {
            return LoadFromAssemblyPath(assemblyPath);
        }

        return null;
    }