gpt4 book ai didi

c# - 从子文件夹解析程序集的正确方法

转载 作者:行者123 更新时间:2023-11-30 21:53:18 24 4
gpt4 key购买 nike

这是我的应用程序文件夹的样子:

Application:
+ App.exe
+ App.exe.config
Application/Plugins:
+ Plugin1 (folder)
Application/Plugins/Plugin1:
+ Plugin1.dll
+ SomeDll.dll

所以主应用程序 App.exe 寻找插件文件夹并将 {PluginName}.dll 加载到内存中以运行它。该插件通常使用它自己的必须加载的依赖程序集(如 SomeDll.dll)。看起来它有时会造成严重的麻烦。我收到异常,例如无法找到依赖程序集的依赖程序集,我不知道为什么。

例如,我的插件必须加载大量额外的 dll,因为插件运行 OwinSelfHost 服务。

因此它必须加载例如:

System.Web.Http.Owin
Owin
Microsoft.Owin
Microsoft.Owin.Host.HttpListener
Microsoft.Owin.Hosting

并且当加载 Microsoft.Owin.Hosting 然后抛出无法加载的异常 Microsoft.Owin

异常看起来像:

Could not load file or assembly 'Microsoft.Owin, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of it's dependencies. File not found.

最佳答案

我编写此方法来解析程序集。它经过调整以满足我的需要。

它基本上将 AssemblyResolve 事件 Hook 到当前应用程序域,以从目录列表中检索请求的程序集。

没有简单的方法可以找到与要解析的命名空间匹配的程序集文件的位置,除非加载一个程序集文件并检查它属于哪个命名空间。

此外,它还会丢弃一些不需要的程序集(如序列化程序、资源...)并检测不是 .NET 程序集的 dll 或 exe。

更好的方法是使用 Global Assembly Cache ,但我们希望我们的插件是完全可移动的。所以就在这里。

public static class AssemblyResolver
{
internal static void Hook(params string[] folders)
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// Check if the requested assembly is part of the loaded assemblies
var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name);
if (loadedAssembly != null)
return loadedAssembly;

// This resolver is called when an loaded control tries to load a generated XmlSerializer - We need to discard it.
// http://connect.microsoft.com/VisualStudio/feedback/details/88566/bindingfailure-an-assembly-failed-to-load-while-using-xmlserialization

var n = new AssemblyName(args.Name);

if (n.Name.EndsWith(".xmlserializers", StringComparison.OrdinalIgnoreCase))
return null;

// http://stackoverflow.com/questions/4368201/appdomain-currentdomain-assemblyresolve-asking-for-a-appname-resources-assembl

if (n.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
return null;

string assy = null;

// Find the corresponding assembly file
foreach (var dir in folders)
{
assy = new[] { "*.dll", "*.exe" }.SelectMany(g => Directory.EnumerateFiles(dir, g)).FirstOrDefault(f =>
{
try { return n.Name.Equals(AssemblyName.GetAssemblyName(f).Name, StringComparison.OrdinalIgnoreCase); }
catch (BadImageFormatException) { return false; /* Bypass assembly is not a .net exe */ }
catch (Exception ex) { throw new ApplicationException("Error loading assembly " + f, ex); }
});

if (assy != null)
return Assembly.LoadFrom(assy);
}

throw new ApplicationException("Assembly " + args.Name + " not found");
};
}
}

这是它的工作原理:

AssemblyResolver.Hook("\Plugins", "\CommonReferences");

每次需要解析一些程序集时,它会获取加载到内存中的那个,否则它会在任何给定的文件夹中搜索。

关于c# - 从子文件夹解析程序集的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33975073/

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