gpt4 book ai didi

c# - 为什么 Powershell 看不到它已经加载了这个程序集?

转载 作者:太空宇宙 更新时间:2023-11-03 11:21:11 27 4
gpt4 key购买 nike

这是一篇很长的文章,请耐心等待。

这个想法是,当应用程序引用 Core.dll(见下文)时,将创建一个类型为 Core 的新对象,并且在这样做时,构造函数将扫描 C:\Problems 文件夹,用于包含使用 IPlugin 接口(interface)的类型的任何 DLL。

当我从控制台应用程序引用 Core.dll 时它起作用。当我从 PowerShell 执行等效操作时,它不起作用,除非 Core.dll 在 GAC 中。

这些是细节:

我有一个程序集 (Core.dll),它是以下内容的结果:

public class Core
{
List<IPlugin> plugins = new List<IPlugin>();

public Core(string path)
{
LoadPlugins(path);
foreach (IPlugin plugin in plugins)
plugin.Work();
}

void LoadPlugins(string path)
{
foreach (string file in Directory.GetFiles(path))
{
FileInfo fileInfo = new FileInfo(file);
Assembly dllAssembly = Assembly.LoadFile(file);
foreach (Type type in dllAssembly.GetTypes())
{
Type typeInterface = type.GetInterface("Problems.IPlugin");
if (typeInterface != null)
plugins.Add((IPlugin)Activator.CreateInstance(
dllAssembly.GetType(type.ToString())));
}
}
}
}

public interface IPlugin
{
string Name {get; set;}
void Work();
}

然后,我有一个单独的程序集 MyPlugin.dll,其中包含以下内容:

public class MyPlugin : IPlugin
{
public string Name { get; set; }
public void Work()
{
Console.WriteLine("Hello, World. I'm a plugin!");
}
}

我用第三个项目 TestApp.exe(以 Core.dll 作为引用)测试了这一切:

static void Main(string[] args)
{
Core core = new Core(@"C:\Problems");
Console.ReadLine();
}

我将 Core.dll 和 MyPlugin.dll 都放到了 C:\Problems 中,TestApp.exe 运行得非常棒!所以,我编写了这个 PowerShell 脚本:

Add-Type -Path "C:\Problems\Core.dll"
$core = New-Object Problems.Core "C:\Problems"

这是我的结果(想象一堆红色):

New-Object : Exception calling ".ctor" with "1" argument(s): "Unable to load one or more o
f the requested types. Retrieve the LoaderExceptions property for more information."
At line:1 char:11
+ New-Object <<<< Problems.Core "C:\Problems"
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

深入研究异常,我发现:

PS C:\Problems> $Error[0].Exception.InnerException.LoaderExceptions
Could not load file or assembly 'Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

到目前为止,我的结论是,当我将 GetTypes() 作为插件加载程序的一部分运行时,它看到 MyPlugin 继承自 Problems.IPlugin,它不知道在哪里可以找到它。但是,我不是已经在 Core.dll 中加载它了吗?

我能解决这个问题的唯一方法是签署 Core.dll 程序集并将其添加到 GAC,但这既烦人又不符合我的目的。

(所有类都在 Problems 命名空间中,我省略了大量清理和过滤逻辑来说明问题。)

最佳答案

您可以通过查看正确的位置来确保处理程序集解决问题来解决此问题,即将您的核心类更改为如下所示:

public class Core
{
List<IPlugin> plugins = new List<IPlugin>();
string path;

public Core(string path)
{
this.path = path;
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
LoadPlugins();
foreach (IPlugin plugin in plugins)
plugin.Work();
}

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var currentAssemblies = AppDomain.CurrentDomain.GetAssemblies();

foreach (var assembly in currentAssemblies)
{
if (assembly.FullName == args.Name)
{
Console.WriteLine("resolved assembly " + args.Name + " using exising appdomain");
return assembly;
}
}

var file = args.Name.Split(new char[] { ',' })[0].Replace(@"\\", @"\");
var dll = Path.Combine(path, file) + ".dll";
Console.WriteLine("resolved assembly " + args.Name + " from " + path);
return File.Exists(dll) ? Assembly.LoadFrom(dll) : null;
}

void LoadPlugins()
{
foreach (string file in Directory.GetFiles(this.path, "*.dll"))
{
FileInfo fileInfo = new FileInfo(file);
Assembly dllAssembly = Assembly.LoadFile(file);
foreach (Type type in dllAssembly.GetTypes())
{
Type typeInterface = type.GetInterface("Problems.IPlugin");
if (typeInterface != null)
plugins.Add((IPlugin)Activator.CreateInstance(
dllAssembly.GetType(type.ToString())));
}
}
}

}

关于c# - 为什么 Powershell 看不到它已经加载了这个程序集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10944771/

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