gpt4 book ai didi

c# - MEF 未检测到插件依赖项

转载 作者:行者123 更新时间:2023-12-04 02:29:30 32 4
gpt4 key购买 nike

我在使用 MEF 和使用插件文件夹时遇到问题。

我有一个通过 MEF 支持插件的主应用程序。主应用程序不引用包含用于多线程的 .NET 任务类型的程序集,但一个或多个插件会引用。

插件位于 Plugins 文件夹中,我使用的是 DirectoryCatalog。

我不断收到 ReflectionTypeLoadException被 MEF 抛出

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.



LoaderExceptions 属性包含一个 FileNotFoundException

"Could not load file or assembly 'System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.":"System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"



该插件正在引用 System.Threading.Tasks通过 Microsoft NuGet 包引用。

这是我的辅助方法:
public static void Compose(IEnumerable<string> searchFolders, params object[] parts)
{
// setup composition container
var catalog = new AggregateCatalog();

// check if folders were specified
if (searchFolders != null)
{
// add search folders
foreach (var folder in searchFolders.Where(System.IO.Directory.Exists))
{
catalog.Catalogs.Add(new DirectoryCatalog(folder, "*.dll"));
}
}

catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

// compose and create plug ins
var composer = new CompositionContainer(catalog);
composer.ComposeParts(parts);
}

public class MEFComposer
{
[ImportMany(typeof(IRepository))]
public List<IRepository> Repositories;

[ImportMany(typeof(ILogging))]
public List<ILogging> LoggingRepositories;

[ImportMany(typeof(IPlugin))]
public List<IPlugin> Plugins;
}

这是我用来调用 MEF 和加载插件的代码。
public void Compose()
{
// try to connect with MEF types
try
{
var parts = new MEFComposer();
MEFHelpers.Compose(new[] { Path.Combine(Application.StartupPath, "Plugins") }, parts);
RepositoryFactory.Instance.Repository = parts.Repositories.FirstOrDefault();
Logging.Repositories.AddRange(parts.LoggingRepositories);
foreach (var plugin in parts.Plugins)
{
this.applicationApi.Plugins.Add(plugin);
plugin.Connect(this.applicationApi);
}
}
catch
{
// ERR: handle error
}
}

为什么 MEF 无法加载插件,即使 Microsoft.Threading.Tasks.dll和相关的程序集文件存在于 Plugins 文件夹中,但不存在于主应用程序 bin 文件夹中?有没有办法告诉 MEF 在 Plugins 文件夹中搜索程序集依赖项?

拥有插件模型意味着我无法预测插件可能引用哪些程序集,因此我无法将它们包含在应用程序的主 bin 文件夹中,这就是为什么我希望所有相关插件和插件依赖项都在插件文件夹中。

最佳答案

您在支持 3rd 方插件时遇到了一个基本问题。您的问题是,当您加载插件时,运行时将在需要时仅在您的 AppDomain 已知的指定文件夹中搜索其引用。那将是 WorkingDirectory of that process, then path etc .

本质上,您正在加载一个需要 System.Threading.Tasks 的插件。 .该 DLL 位于您的 /Plugin 中文件夹。当 .net 加载您的插件时,它将搜索该程序集,但无法找到它,因为它位于 /Plugin 中。文件夹并失败。

有几个解决方案。

  • 不要使用插件文件夹

  • 这将是最简单的解决方案,当所有程序集(包括第 3 方库的引用)都位于您的 WorkingDirectory 中时,.net 将可以轻松找到该插件的所有引用。
  • 将插件文件夹添加到您的探测路径

  • 这将扩展 .net 将搜索 3rd 方引用的路径:
    https://docs.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies#locating-the-assembly-through-probing
  • 为每个插件使用 AppDomains。

  • AppDomain 是我的选择,因为它不仅允许您在其“自己的”容器中加载程序集,而且还可以仅为插件模拟工作目录。例如,如果某个插件使用与您的应用程序相同的框架但使用不同的版本,这会很方便。
  • 自己加载依赖

  • 这将是解决这个问题的“直接”方法。您可以将每个程序集加载为 ReflectionOnly , 确定所有依赖项,然后加载这些。这几乎可以保证工作正常。

    4.1. AssemblyResolve 事件

    这只是如何“重定向”.net 以从 PluginFolder 加载程序集的另一种方式
    https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.assemblyresolve?view=netframework-4.8

    编辑:
    AssemblyCatalog也有一定的问题,它使用 Assembly.Load而不是 Assembly.LoadFrom加载给定的程序集。这是您问题的重要组成部分,如 LoadFrom将探测程序集起源于其依赖项的路径,其中 Load没有。

    https://github.com/JPVenson/MSEF/blob/master/JPB.Shell/JPB.Shell.MEF/Model/StrongNameCatalog.cs

    您可以使用类似使用 LoadFrom 的目录。
    免责声明:我是该项目的创建者。

    关于c# - MEF 未检测到插件依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28004812/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com