Это действительно длинный, так что повесьте трубку.Почему Powershell не видит, что он уже загрузил эту сборку?
Идея состоит в том, что приложение, ссылающееся на Core.dll (см. Ниже), создаст новый объект типа Core
, и при этом конструктор сканирует папку C:\Problems
для любых DLL, содержащих тип который использует интерфейс IPlugin
.
Он работает, когда я ссылаюсь на 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
Бурение вниз в Exception, я нахожу это:
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, который он не k теперь, где найти. Но разве я не загрузил его в Core.dll?
Единственный способ, которым я могу обойти это, - подписать сборку Core.dll и добавить ее в GAC, но это и раздражает, и не подходит для моих целей.
(Все классы в пространстве имен проблем, и я опустил тонну очистки и фильтрации логики, чтобы проиллюстрировать эту проблему.)
Это работает, и это мой лучший вариант, но для меня это все еще не имеет смысла. Зачем мне перезагружать Core.dll? Я запускаю LoadPlugins() из его экземпляра уже! –
Кроме того, это заставляет меня отслеживать, где находится Core.dll. Моя цель состоит в том, что я включаю только Core.dll один раз, а затем указываю, где находятся плагины. –
Обнаружено обходное решение. Я отредактировал, чтобы завершить свой ответ. У кого-нибудь есть идея, почему это происходит? Не имеет смысла сначала смотреть в текущем AppDomain? Почему это только проблема при запуске из PowerShell? –