Не удается получить типы из сборки после ReflectionOnlyLoadFrom
Я проконсультировался с кодом на сайте http://codeproject.com с заголовком «Загрузка сборок из любого места в новый домен приложений» Мариуса Бансила, но я проверил ошибку, как на прилагаемом изображении, в настоящее время я не знаю, разрешить ли вы, надеюсь, вы поможете, спасибо.
Код ссылки https://www.codeproject.com/Articles/453778/Loading-Assemblies-from-Anywhere-into-a-New-AppDom#_articleTop
Контрольная работа
public class Program
{
[STAThread]
public static void Main()
{
var project = @"D:\Github\BeyConsPlugin\BeyConsProject\bin\x64\Debug\BeyConsRevitProject.dll";//Path to assembly
var manager = new AssemblyReflectionManager();
var success = manager.LoadAssembly(project, Guid.NewGuid().ToString());
if (success)
{
var result = manager.Reflect(project, (a) =>
{
return a.GetTypes();
});
Console.WriteLine(string.Join("\n", result.Select(x => x.Name)));
}
Console.ReadKey();
manager.UnloadAssembly(project);
}
}
Ошибка
Ответы
Резольвер сборки не установлен
В коде Мариуса есть ошибка, связанная AssemblyReflectionProxyс тем, что ассемблерный преобразователь не устанавливается, если вы вызываете в LoadAssemblyотличие от того, Reflect<>что установлено.
В зависимости от того, как создается дочерний домен приложения, при загрузке сборок он может иметь доступ только к папке, указанной при создании. Если вам нужно собрать зонд в другом месте для сборки или ее зависимостей, вам понадобится Assembly Resolver. Когда .NET ищет сборку для домена, он вызывает ваш обработчик, как указано в ReflectionOnlyAssemblyResolveсобытии сборки . Если не указан или если преобразователю не удается найти сборку, он всплывает и генерирует исключение сбоя загрузки.
Предлагаю вам изменить код:
public class AssemblyReflectionProxy : MarshalByRefObject
{
private string _assemblyPath;
public void LoadAssembly(String assemblyPath)
{
try
{
_assemblyPath = assemblyPath;
Assembly.ReflectionOnlyLoadFrom(assemblyPath);
}
catch (FileNotFoundException)
{
// Continue loading assemblies even if an assembly
// cannot be loaded in the new AppDomain.
}
}
...к:
public class AssemblyReflectionProxy : MarshalByRefObject
{
private string _assemblyPath;
public void LoadAssembly(String assemblyPath)
{
try
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve // <---- add me
+= OnReflectionOnlyResolve;
_assemblyPath = assemblyPath;
Assembly.ReflectionOnlyLoadFrom(assemblyPath);
}
catch (FileNotFoundException)
{
// Continue loading assemblies even if an assembly
// cannot be loaded in the new AppDomain.
}
}
Вы можете увидеть это в исходном коде Саши , на котором Мариус основал свой.
Добавить положение для разрешения путей
Другая проблема с кодом заключается в том, что оба предполагают, что при загрузке одной сборки все зависимые сборки находятся в одной папке, что может быть не всегда.
Измените, AssemblyReflectionProxyчтобы включить список путей для проверки:
public List<string> ResolvePaths { get; set; }
Затем измените OnReflectionOnlyResolve, чтобы он выглядел следующим образом:
private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
{
Assembly loadedAssembly =
AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
.FirstOrDefault(
asm => string.Equals(asm.FullName, args.Name,
StringComparison.OrdinalIgnoreCase));
if (loadedAssembly != null)
{
return loadedAssembly;
}
foreach (var tryFolder in ResolvePaths)
{
var asmName = args.Name.Split(',');
var assemblyPath = Path.Combine(tryFolder, asmName[0] + ".dll");
if (!File.Exists(assemblyPath))
return null;
return Assembly.ReflectionOnlyLoadFrom(assemblyPath);
}
}
Что в имени?
В обеих статьях пренебрегали мелким шрифтом при использовании ReflectionOnlyLoad. Хотя Саша хотя бы упомянул, что его код предназначен для «генератора кода», я не могу не задаться вопросом, что обе статьи с их « Loading Assemblies.... в новый домен приложения» , возможно, в какой-то мере подлежат интерпретации.
Цель ReflectionOnlyLoadвсего этого - для размышлений . Если вы загрузите сборку с помощью этого метода, вы не сможете выполнить в ней какой-либо код. Вдобавок и поначалу несколько удивительно для большинства программистов-рефлекторов сборки, включая меня, то, что вызов GetCustomAttributesтакже завершится ошибкой (потому что он пытается «создать экземпляры» типов в сборке).
Если вы пишете свою собственную систему подключаемых модулей, в которой каждый подключаемый модуль имеет свой собственный домен приложения, Assemblyметоды отражения и загрузки полезны на разных этапах конвейера загрузки системы подключаемых модулей:
- первый проход - использовать
ReflectionOnlyLoadкак способ проверить подключаемый модуль, чтобы убедиться, что он действителен; возможно, вы хотите провести некоторые проверки безопасности, зная, что ни один из кодов плагинов не может работать на этом этапе - второй проход - после проверки плагина можно спокойно
Load/LoadFromсборку и выполнить код