Impossible d'obtenir les types de l'assembly après ReflectionOnlyLoadFrom
J'ai consulté le code sur le site http://codeproject.com avec le titre "Chargement d'assemblys de n'importe où dans un nouvel AppDomain" de Marius Bancila, mais j'ai testé l'erreur comme dans l'image ci-jointe, actuellement, je ne sais pas résoudre, j'espère que vous aiderez, merci.
Code de lien https://www.codeproject.com/Articles/453778/Loading-Assemblies-from-Anywhere-into-a-New-AppDom#_articleTop
Test
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);
}
}
Erreur
Réponses
Le résolveur d'assemblage n'est pas défini
Le code de Marius a un bogue en AssemblyReflectionProxyce qui concerne le fait que le résolveur d'assemblage n'est pas défini si vous appelez LoadAssemblycontrairement à Reflect<>ce qui le fait.
Selon la manière dont un domaine d'application enfant est créé, lors du chargement des assemblys, il peut uniquement avoir accès au dossier comme spécifié lors de la création. Si vous avez besoin de rechercher l'assemblage ailleurs pour l'assemblage ou ses dépendances, vous avez besoin d'un résolveur d'assemblage. Lorsque .NET recherche un assembly pour un domaine, il appellera votre gestionnaire comme spécifié dans l' ReflectionOnlyAssemblyResolveévénement de l'assembly . Si ce n'est pas spécifié ou si le résolveur ne parvient pas à localiser l'assemblage, il apparaîtra et lèvera une exception d'échec de chargement.
Je vous suggère de changer le code de:
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.
}
}
Vous pouvez le voir dans le code original de Sacha, celui sur lequel Marius a basé le sien.
Ajouter une disposition pour résoudre les chemins
L'autre problème avec le code est que les deux supposent que lors du chargement d'un assembly, tous les assemblys dépendants se trouvent dans le même dossier, ce qui n'est pas toujours le cas.
Modifiez AssemblyReflectionProxypour inclure une liste de chemins dans lesquels sonder:
public List<string> ResolvePaths { get; set; }
Puis modifiez OnReflectionOnlyResolve pour ressembler à ce qui suit:
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);
}
}
Qu'est-ce qu'il y a dans un nom?
Les deux articles ont négligé de souligner les petits caractères lors de l'utilisation ReflectionOnlyLoad. Bien que Sacha ait au moins mentionné que son code était destiné à un "générateur de code", je ne peux m'empêcher de me demander que les deux articles avec leur " Loading Assemblies.... into a New AppDomain" sont peut-être quelque peu sujets à interprétation.
Le but de ReflectionOnlyLoadn'est que cela - pour la réflexion . Si vous chargez un assembly via cette méthode, vous ne pouvez y exécuter aucun code. De plus et quelque peu surprenant au début pour la plupart des programmeurs de réflecteurs d'assemblage, y compris moi, c'est que l'appel échoueraGetCustomAttributes également (car il tente d ' «instancier» des types dans l'assemblage).
Si vous écrivez votre propre système de plug-in dans lequel chaque plug-in a son propre domaine d'application, les Assemblyméthodes de réflexion et de chargement sont utiles pour les différentes étapes du pipeline de chargement du système de plug-in:
- premier passage - à utiliser
ReflectionOnlyLoadpour inspecter le plug-in pour voir s'il est valide; peut-être voulez-vous exécuter des contrôles de sécurité en sachant qu'aucun code de plug-ins ne peut s'exécuter pendant cette phase - deuxième passe - après avoir vérifié le plug-in, vous pouvez en toute sécurité
Load/LoadFroml'assembly et exécuter le code