В настоящее время я работаю над проектом, который должен работать в качестве платформы для нескольких дополнений, которые должны быть загружены во время выполнения.
Мне поручено иметь следующую структуру в папке приложения:
- 2 Каталоги с подпапками. Один с именем " / addons " для надстроек и один с именем " / ref " для любых дополнительных ссылок, которые эти надстройки могут использовать (например,
System.Windows.Interactivity.dll
) - Когда При выборе одной из надстроек в меню приложения приложение .dll должно быть загружено во время выполнения, и должна быть открыта предварительно заданная точка входа
- Должны быть загружены все ссылки на вновь загруженную сборку. aswell.
Я знаю подпапку и имя файла при загрузке дополнения, поэтому я просто использую Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location))
и Path.Combine()
, чтобы построить путь к .dll, а затем загрузить его через Assembly.LoadFile()
перед использованием отражения с assembly.GetExportedTypes()
, чтобы найти класс, который наследуется для моего 'EntryPointBase', а затем создать его с Activator.CreateInstance()
.
Однако, как только у меня появятся ссылки в моем дополнении, System.IO.FileNotFoundException
с таргетингом на ссылку появится на assembly.GetExportedTypes()
Я создал метод для загрузки всех сборок, на которые есть ссылки, даже сделал рекурсивным загрузку всех ссылок из ссылок, например это:
public void LoadReferences(Assembly assembly)
{
var loadedReferences = AppDomain.CurrentDomain.GetAssemblies();
foreach (AssemblyName reference in assembly.GetReferencedAssemblies())
{
//only load when the reference has not already been loaded
if (loadedReferences.FirstOrDefault(a => a.FullName == reference.FullName) == null)
{
//search in all subfolders
foreach (var location in Directory.GetDirectories(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)))
{
//GetDirectoriesRecusrive searchs all subfolders and their subfolders recursive and
//returns a list of paths for all files found
foreach (var dir in GetDirectoriesRecusrive(location))
{
var assemblyPath = Directory.GetFiles(dir, "*.dll").FirstOrDefault(f => Path.GetFileName(f) == reference.Name+".dll");
if (assemblyPath != null)
{
Assembly.LoadFile(assemblyPath);
break; //as soon as you find a vald .dll, stop the search for this reference.
}
}
}
}
}
}
и сделано убедитесь, что все ссылки загружены путем проверки AppDomain.CurrentDomain.GetAssemblies()
, но исключение остается прежним.
Работает, если либо все сборки находятся непосредственно в папке приложения, либо если на все ссылки в надстройке уже ссылаются само приложение запуска. Оба способа не подходят для моего случая, потому что в этой файловой системе требуются повышенные требования, и дополнения с новыми ссылками должны загружаться, не касаясь самого приложения.
Вопрос:
Как загрузить сборки из одной подпапки и их ссылки из другой без System.IO.FileNotFoundException
?
Дополнительная информация :
- Приложение в новом формате .csproj и работает на
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
, хотя поддержка net472 должна быть вскоре прекращена (в настоящее время все еще отлаживается в net472) - Most Надстройки по-прежнему имеют старый формат .csproj в net472
- , подпапка ref также структурирована в подпапках (dev express, system, et c.), В то время как подпапка надстроек больше не имеет подпапок.