web-dev-qa-db-fra.com

Comment obtenir tous les types dans un assemblage référencé?

Pour une raison quelconque, je n'arrive pas à obtenir la liste des types dans une Assemblée référencée. Non seulement cela, je ne peux même pas sembler pouvoir arriver à cette assemblée référencée.

J'ai essayé AppDomain.CurrentDomain.GetAssemblies(), mais il ne renvoie que les assemblys qui ont déjà été chargés en mémoire.

J'ai essayé Assembly.GetExecutingAssembly().GetReferencedAssemblies(), mais cela retourne simplement mscorlib.

Qu'est-ce que je rate?

32
AngryHacker

Notez que Assembly.GetReferencedAssemblies inclut uniquement un assemblage particulier si vous utilisez réellement un type de cet assemblage dans votre assemblage (ou un type que vous utilisez dépend du type figurant dans cet assemblage). Il ne suffit pas d'inclure simplement un assemblage dans la liste de références dans Visual Studio. Peut-être cela explique-t-il la différence de rendement par rapport à vos attentes? Je remarque que si vous vous attendez à pouvoir obtenir tous les assemblys figurant dans la liste des références dans Visual Studio en utilisant une réflexion impossible. les métadonnées pour l’Assemblée ne contiennent aucune information sur les assemblées dont l’Assemblée n'est pas dépendante.

Cela dit, une fois que vous avez récupéré la liste de tous les assemblys référencés, vous devriez énumérer ci-dessous tous les types de ces assemblys:

foreach (var assemblyName in Assembly.GetExecutingAssembly().GetReferencedAssemblies()) {
    Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in Assembly.GetTypes()) {
        Console.WriteLine(type.Name);
    }
}

Si vous avez besoin des assemblys référencés dans Visual Studio, vous devrez analyser le fichier csproj. Pour cela, consultez l’élément ItemGroup contenant les éléments Reference.

Enfin, si vous savez où réside un assembly, vous pouvez le charger à l'aide de Assembly.LoadFile et procéder comme indiqué ci-dessus pour énumérer les types qui résident dans cet assembly chargé.

57
jason

La méthode GetReferencedAssemblies optimise en principe le processus de découverte sur votre assembly, en ignorant les assemblys pour lesquels vous ne disposez pas de référence explicite.

Supposons que vous avez un projet B et un projet C référençant le projet B. Vous créez maintenant un nouveau projet A avec une référence à C (et non à B).

Lorsque vous appelez Assembly.Load("C path").GetReferenceAssemblies, il renverra simplement B si vous n'avez jamais fait référence à une classe, une énumération, une interface ... qui faisait partie de l'assembly C.

En guise de solution de contournement, vous pouvez créer des instances factices de classes présentes dans C.

Assembly.C.Class1 dummyInstance = new Assemply.C.Class1();

Personnellement, j’ai utilisé cette solution au cas où vous auriez besoin de séparer toutes vos interfaces dans un projet Core, et dans Core.Proj1 d’indiquer à vos classes les interfaces utilisées dans Core pour une découverte ultérieure dans votre Assembly principal. Gardez à l'esprit que la réflexion a un impact sur les performances lorsque vous chargez plusieurs assemblys. Ne vous contentez donc pas d'une solution permettant de découvrir un répertoire et de charger tous les assemblys pour obtenir les types dont vous avez besoin. Donc, à partir de là, vous pouvez continuer avec le code suggéré par @jason

foreach(var ....)
  Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in Assembly.GetTypes()) {
        Console.WriteLine(type.Name);
0
Zinov

J'ai également atterri dans une situation où je devais obtenir tous les assemblys figurant dans la liste de références dans Visual Studio. 

J'ai utilisé le travail suivant pour le faire.

var path = AppContext.BaseDirectory;  // returns bin/debug path
var directory = new DirectoryInfo(path);

if (directory.Exists)
{
    var dllFiles = directory.GetFiles("*.dll");  // get only Assembly files from debug path
}
0
Deepak Ageeru