从不同文件夹引用第三方组件,而不是重新分配

问题描述 投票:0回答:1

这确保每个插件都在其自己的上下文中加载,以便插件可以成功地使用插件之间具有冲突版本的程序集。 我的插件中的一个使用我不允许重新分配的第三方DLL,因此用户需要自己下载此(以及Aquire a使用使用许可证)。 如果这是一个定期在Windows/Linux中运行的独立应用程序,这不会引起任何问题,因为我可以指示用户将DLL直接复制到与插件的同一文件夹中。 我希望将其创建为公共Docker映像,该图像可防止用户直接复制到插件文件夹中。

我最初的想法是将第三方DLL放入将映射到docker容器中的“数据”文件夹中(即将写入日志)。在项目文件中引用程序集工作正常:

<ItemGroup> <Reference Include="Some3rdParty"> <HintPath>..\..\data\lib\Some3rdParty.dll</HintPath> <Private>false</Private> <ExcludeAssets>runtime</ExcludeAssets> </Reference> </ItemGroup>

所有的内容都可以很好地编译。

但是,当我的主要应用程序试图加载插件组件时,它抱怨它找不到它,这并不奇怪,因为构建解决方案时没有复制到插件文件夹(这是正确的,因为我无法重新分发它):

System.Reflection.ReflectionTypeloadexception:无法加载一种或多种请求类型。

因此,问题是:如何将插件引用作为第三方组件,并从完全不同的文件夹中加载它,而我的主应用程序可以加载插件而没有错误?

Microsoft文章指示您创建一个看起来像这样的
Some3rdParty.dll

PluginLoadContext

解决我的问题的解决方案也是发送一个其他文件夹名称,以从

class PluginLoadContext : AssemblyLoadContext { private AssemblyDependencyResolver _resolver; public PluginLoadContext(string pluginPath) { _resolver = new AssemblyDependencyResolver(pluginPath); } protected override Assembly Load(AssemblyName assemblyName) { string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); if (assemblyPath != null) { return LoadFromAssemblyPath(assemblyPath); } return null; } protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) { string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); if (libraryPath != null) { return LoadUnmanagedDllFromPath(libraryPath); } return IntPtr.Zero; } }
的构造函数加载到

List<string>

的构造函数,以便如果初始
PluginLoadContext

失败,则可以尝试其中之一:

c# .net plugins reflection assemblies
1个回答
0
投票

I已经从插件文件夹中读取

public class PluginLoadContext(string pluginPath, List<string> additionalAssemblyFolders) : AssemblyLoadContext
{
    private AssemblyDependencyResolver _resolver;
    private List<string> _additionalAssemblyFolders;

    public PluginLoadContext(string pluginPath, List<string> additionalAssemblyFolders)
    {
        _resolver = new AssemblyDependencyResolver(pluginPath);
        _additionalAssemblyFolders = additionalAssemblyFolders;
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
        if (assemblyPath != null)
        {
            return LoadFromAssemblyPath(assemblyPath);
        }

        if (additionalAssemblyFolders == null)
        {
            return null;
        }

        foreach (string assemblyFolder in _additionalAssemblyFolders)
        {
            string potentialAssemblyPath = Path.Combine(assemblyFolder, $"{assemblyName.Name}.dll");
            FileInfo fi = new(potentialAssemblyPath);
            if (fi.Exists)
            {
                return LoadFromAssemblyPath(fi.FullName);
            }
        }

        return null;
    }

    protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
    {
        string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
        if (libraryPath != null)
        {
            return LoadUnmanagedDllFromPath(libraryPath);
        }

        foreach (string assemblyFolder in additionalAssemblyFolders)
        {
            string potentialAssemblyPath = Path.Combine(assemblyFolder, $"{unmanagedDllName}.dll");
            FileInfo fi = new(potentialAssemblyPath);
            if (fi.Exists)
            {
                return LoadUnmanagedDllFromPath(fi.FullName);
            }
        }

        return IntPtr.Zero;
    }
}
,所以现在我可以在我的

appsettings.json
列表中添加一个清单,然后将其发送到创建的位置。
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.