8
votes

Comment puis-je obtenir un type d'un assemblage chargé d'un autre dossier?

J'utilise le code suivant:

Assembly.LoadFile("the assembly in another folder");
var type = Type.GetType("the full name of the type");


3 commentaires

Est-ce que ce assemblage est-il associé à la langue d'assemblage?


@Kirilkirov: Non. C'est un type dans .NET.


@Austin - Ah, merci :) J'ai été induit en erreur par la balise.


4 Réponses :


10
votes

type.getType recherche uniquement les types de l'assemblage d'appel et les types dans mscorlib.dll, sauf si vous ne transmettez pas le nom qualifié de type du type. voir ici.

Edit

Il semble que type.getype ne soit capable de récupérer les instances de type des assemblages dans le contexte de charge. Les assemblages chargés à l'aide de LIFILE sont dans Pas de contexte et ceux chargés à l'aide de LoadFrom sont dans la charge du contexte; Aucun de ces contextes ne vous permet d'utiliser type.getype de sorte que la résolution échouera. Cet article montre que Type Les informations peuvent être récupérées pour un ensemble lorsque le répertoire à utiliser est ajouté en tant que privé sondage car il finira ensuite dans le contexte de la charge mais échouera dans d'autres contextes. < / p>


4 commentaires

J'ai passé le nom de l'Assemblée qualifié, y compris l'espace de noms, le nom de type, le nom de montage et la version, joben public.


@Cuipengfei Juste pour éliminer l'évidence, êtes-vous certain que le nom qualifié de montage correspond exactement à la valeur sensible à la casse que vous obtiendriez si vous avez référencé statilement l'assemblage et appelé typeof (typename) .AssemblyqualifiedName ?


@Cuipengfei: J'ai essayé d'utiliser type.gettype sans succès, alors je voudrais endorcer @évanwilliams réponse comme la meilleure solution.


Pour une raison quelconque, l'article cité dans cette réponse n'est plus disponible - Quiconque sachant comment recommencer?



1
votes

Vous pouvez essayer ceci ....

assemblage.GetAssembly suppose que vous avez une instance du type, et Type.getType suppose que vous avez le nom de type complet qui inclut le nom de l'assemblage. P>

Vous pouvez donner un chemin que l'assemblage est situé ..... p>

Si vous n'avez que le nom de type de base, vous devez faire quelque chose de plus comme ceci: P>

public static String GetAssemblyNameContainingType(String typeName) 
{
    foreach (Assembly currentassembly in AppDomain.CurrentDomain.GetAssemblies()) 
    {
        Type t = currentassembly.GetType(typeName, false, true);
        if (t != null) {return currentassembly.FullName;}
    }

    return "not found";
}


2 commentaires

Faites attention lorsque vous chargez des assemblages car une fois que vous les avez chargées dans une Appdomain, vous ne pouvez plus les décharger. Si vous avez beaucoup d'assemblages à charger, pensez à créer une appdomaine distincte qui effectuera les travaux de traitement des assemblages de traitement et du résultat du retour, après quoi il peut être publié.


Je ne le recommanderais pas. Au lieu de cela, raccordez-vous au AppDomain.assemblyResolve événement. De cette façon, vous ne renvoyez que l'assemblage requis, où dans le code ci-dessus, vous recherchez chaque ensemble chargé, plus vous commencez à charger ceux qui ne sont pas actuellement nécessaires .



2
votes

Le moyen le plus simple de faire est de passer simplement la valeur de retour de l'assemblage.loadfile dans une variable et appelez gettype sur elle comme ceci: xxx

Vous voudrez peut-être envisager de conserver une référence à cet assemblage si vous voulez souvent tirer des types de cela, ou faire ce que les autres ont suggéré et apporter une méthode plus générique qui boucle à travers tous les assemblages chargés.


0 commentaires

5
votes

la manière "appropriée" (MS recommandée) de faire cela, lorsque vous devez utiliser type.getype (chaîne) code> sur les types d'assemblages qui ne sont pas dans le contexte de la charge mais dans la charge à partir de ou Contexte non contextuel, est de se lier au appdomain . AssemblblierResolve code> événement. Le code suivant est relativement efficace:

// this resolver works as long as the assembly is already loaded
// with LoadFile/LoadFrom or Load(string) / Load(byte[])
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies()
              where a.GetName().FullName == args.Name
              select a).FirstOrDefault();

    if(asm == null)
         throw FileNotFoundException(args.Name);     // this becomes inner exc

    return asm;
}

// place this somewhere in the beginning of your app:
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;


0 commentaires