2008-11-20 6 views
42

J'essaie de comprendre les différences entre Assembly.Load et Assembly.ReflectionOnlyLoad.C# Assembly.Load vs Assembly.ReflectionOnlyLoad

Dans le code ci-dessous je tente de trouver tous les objets dans un ensemble donné héritant d'une interface donnée:

var myTypes = new List<Type>(); 

var assembly = Assembly.Load("MyProject.Components"); 

foreach (var type in assembly.GetTypes()) 
{ 
    if (type.GetInterfaces().Contains(typeof(ISuperInterface))) 
    { 
     myTypes.Add(type); 
    } 
} 

Ce code fonctionne bien pour moi, mais je faisais des recherches dans d'autres possiblement de meilleures alternatives et rencontré la méthode Assembly.ReflectionOnlyLoad().

Je suppose que depuis que je ne suis pas charger ou d'exécuter l'un des objets, essentiellement juste interroger sur leurs définitions que je pourrais utiliser ReflectionOnlyLoad pour une légère augmentation de la performance ...

Mais il se trouve que quand je changer Assembly.Load à Assembly.ReflectionOnlyLoad je reçois l'erreur suivante quand il appelle assembly.GetTypes():

System.Reflection.ReflectionTypeLoadException: 

Impossible de charger un ou plusieurs des types demandés. Récupérez la propriété LoaderExceptions pour plus d'informations .

Je suppose que le code ci-dessus était juste en train de faire la réflexion et « regarder » la bibliothèque ... mais est-ce une sorte d'instance de l'incertitude de Heisenberg Principe selon lequel la recherche à la bibliothèque et les objets qu'il est en réalité essayer de les instancier d'une manière ou d'une autre?

Merci, Max

Répondre

23

Selon la réponse de Jon, il serait utile de savoir ce qui est dans LoaderExceptions. Au lieu de cette information, je pense que je peux hasarder une estimation. De MSDN:

Si l'ensemble a des dépendances, la méthode de ReflectionOnlyLoad ne les charger. Si vous avez besoin de les examiner, vous devez les charger vous-même.

Vous devez attacher un gestionnaire à AppDomain.ReflectionOnlyAssemblyResolve pour aider le CLR à charger les dépendances de l'assemblage que vous chargez. Avez-vous fait cela?

8

Je crois que votre compréhension générale des différences entre Load et ReflectionOnlyLoad est correcte. Le problème ici (je pense) est que même pour charger simplement un type, le CLR doit lire les métadonnées de l'assembly le type lui-même est défini en ainsi charger les métadonnées de chaque assembly les ancêtres du type sont définis en. Vous devez donc appeler Assembly.ReflectionOnlyLoad sur tous les assemblys qui définissent les types ancêtres des types que vous chargez.

Pour donner un exemple, supposons que la classe suivante soit définie dans l'assembly A.dll.

public class MyBase 
{ 
    public void Foo() { } 
} 

et la classe suivante définie dans l'assembly B.dll.

public class MySubclass : MyBase 
{ 
} 

Lorsque vous appelez Assembly.GetTypes sur l'assembly B.dll, le CLR va essayer de charger le type MySubclass et tous ses membres. Parce que la méthode Foo est définie dans MyBase dans l'assembly A.dll (et n'existe nulle part dans les métadonnées de B.dll), le CLR lancera les exceptions de chargement de type si l'assembly A.dll n'a pas été chargé.

6

Les méthodes ReflectionOnly sont la seule façon de charger un assemblage spécifique sur le disque pour l'examiner sans passer par les règles habituelles Load/LoadFrom. Par exemple, vous pouvez charger un assembly sur disque avec la même identité qu'un assembly dans le GAC. Si vous avez essayé ceci avec LoadFrom ou LoadFile, l'assembly GAC est TOUJOURS chargé.

De plus, vous ne pouvez pas appeler GetCustomAttributes (...) sur l'instance Assembly de retour, car cela va tenter d'instancier les attributs sur l'assembly, qui sont ReflectionOnly. Vous devez utiliser les méthodes statiques de la classe CustomAttributeData pour cela.

Aucun type dans un assembly chargé via ReflectionOnly ne peut être instancié.

1

Aucune méthode ne peut être exécutée à partir de l'assemblage, chargé avec ReflectionOnlyLoad(), vous obtiendrez InvalidOperationException. C'est donc un moyen sûr de déterminer le contenu de l'assemblage en utilisant la réflexion.