8
votes

Comment obtenir des attributs personnalisés d'un assemblage qui n'est pas chargé (vraiment)

Nous savons tous que l'assemblage peut être interrogé pour les attributs à l'aide de la méthode GetCustomattributes. Je veux utiliser cela pour identifier un module d'extension pour mon application. Cependant, pour éviter de charger chaque assemblée, je préfère une approche défensive:

  1. à l'aide de l'assemblage.reflectionnloadloadfrom Pour obtenir plus de détails sur un assembly (a-t-il mon moduleAttribute?)

  2. Si le ModuleatTribute est trouvé, je le chargerai enfin à l'aide de l'assemblage.Loadfrom

    Malheureusement, il semble qu'il n'y aient aucun moyen d'obtenir les attributs d'un assemblage, qui est chargé dans le contexte de réflexion-seul: xxx

    échoue avec une invalidoppationException ("Il est illégal de réfléchir aux attributs personnalisés d'un type chargé via réflectionnygetype") et xxx

    échoue avec réflectionTypeeloadException en raison d'ensembles dépendants non chargés.

    Comment obtenir les attributs sans

    1. polluer mon domaine d'application avec des types inutiles (peut-être nuisibles) en appelant Assembly.Loadfrom
    2. La nécessité de charger tous les assemblages référencés
    3. La nécessité de domaines d'application distincts (l'a donné un essai court, sentait encore plus pita)

      ?


0 commentaires

6 Réponses :


0
votes

Si j'étais vous, je cache des métadonnées d'assemblage dans, par exemple, des fichiers XML. En utilisant cette approche, vous éliminez complètement le besoin de charger quoi que ce soit. Et vous pouvez stocker des informations encore, pour calculer lesquelles vous devez effectuer une opération de consommation de temps.

Vous pouvez avoir des fichiers XML prévenusés ou générés à la volée en numérisant tous les assemblys existants.


4 commentaires

N'aime pas cette approche, car elle s'appuie sur des métadonnées supplémentaires. Ce n'est pas beaucoup mieux que le codage dur dans lequel le répertoire d'un assemblage avec nom de fichier fixe doit être situé.


Il repose sur des métadonnées en cache, pas plus. Vous extrayez les métadonnées des assemblées et stockez-les dans votre cache (fichiers XML ou autre). Il est plus rapide et mieux en train de lire des assemblées. De plus, cette approche est beaucoup plus extensible car, après un certain temps, vous finirez avec quelque chose, vous ne pourrez pas extraire de l'assemblage sans le charger.


Peut-être que je ne vous ai pas, mais qui crée le cache de métadonnées? Il nécessite que le Créateur fournisse une description de métadonnées valide ou moi de la créer quelque peu plus tôt avant de tenter de charger le module. Dans les deux sens, quelqu'un devra faire cela et le problème est exactement le même


"Ou moi de la créer un peu plus tôt avant de tenter de charger le module" - Oui. Et vous devez le faire juste une fois. Par exemple, lors de l'installation du logiciel. Après cela, il n'y a pas d'impact sur la performance lorsque vous lisez des métadonnées à partir du cache que vous avez généré.



2
votes

Avez-vous examiné le cadre Microsoft AdidIn.

Il permet de charger des modules (Admin) dans les différents domaines et processus d'applications et interrogez par interface sur des données d'attribut spécifiques.

Il pourrait ne pas Soyez ce que vous voulez, mais pourrait valoir un look.

http://msdn.microsoft.com/en-us/library/bb384200.aspx xxx

et avec un peu de linq, vous pouvez la questionner < / p> xxx


3 commentaires

MAF ou même mef semble être une option, oui. Malheureusement, cela nécessiterait une modification de la conception du plugin, qui n'est pas directement (et non obligatoire) développée par nous.


Cela pourrait être un problème si le plugin n'est pas facilement enveloppable


Mais je suppose que je suppose que cela défierait votre besoin si les plugins externes doivent être recompansés par vous



4
votes

Après avoir vérifié toutes les réponses et faire plus de recherches, il semble qu'il n'y ait tout simplement aucun moyen de faire ce que je veux: Vérifiez si un assembly est un module d'extension valide avant de le charger dans le domaine de l'application.

soit je dois charger l'assemblage à inspecter dans un autre domaine d'application, inspecter là-bas là-bas et quand il réussit à le charger dans mon domaine d'application actuel ou que je dois stocker des métadonnées de l'assemblage en dehors de l'assemblage lui-même et faites confiance à cette situation. métadonnées. L'option on n'est pas possible à cause des restrictions architecturales, l'option deux déplace simplement le problème mais ne la résout pas.

Probablement la meilleure alternative consiste à utiliser le cadre d'extensibilité géré, mais cela n'est malheureusement pas aussi facile dans la configuration actuelle.

Je me retrouve avec confiance qu'il n'y a rien de "mauvais" dans le répertoire des modules et de tout charger (avec des vérifications pour ne pas dépasser la taille de fichier maximale et ne pas être chargé déjà).

Néanmoins, merci de vos idées.


0 commentaires

5
votes

Il est possible de charger (réflexion uniquement) des assemblages avec des dépendances.

AppDomain.CurrentDomain.reflectionnlyAssemblyResolve + = (S, E) => assemblage.reflectionnloadload (nom e.name);

réparerait les échecs lors du chargement, en supposant qu'ils sont tous dans le même dossier.


2 commentaires

Pouvez-vous élaborer avec une meilleure réponse ici? On dirait que vous avez trouvé un travail autour ... mais je ne peux pas le faire fonctionner.


Ce n'est pas une solution de contournement mais une solution valide. Lorsque l'assemblage contenant les types requis ne peut pas être découvert dans un contexte de réflexion, l'événement réfdacto-refletOnlylblyResolve est viré. Vous pouvez charger manuellement l'assembly alors.



2
votes

Si vous remotionnez ou utilisez une configuration proxy, vous aurez quelque chose de similaire à celui-ci: XXX PRE>

Cependant, si vous obtenez une exception dans l'ensemble du domaine, cela ressemble probablement à ceci: P>

{system.invalidoperationException: il est illégal de réfléchir sur le Attributs personnalisés d'un type chargé via réflectionnygetType (voir Assembly.reflectionOnly) - Utilisez plutôt CustomAttributeTata à la place. P> blockQuote>

Voici le code qui déclenchera celle de la 1ère ligne. P>

foreach (CustomAttributeData cad in assembly.GetCustomAttributesData().Where(a => a.AttributeType == typeof (AssemblyTitleAttribute)))
  return cad.ConstructorArguments.FirstOrDefault().Value as String;
return String.Empty;


0 commentaires

3
votes

vraiment em> la question ancienne, mais cela a été possible depuis .net 2.0. Le problème est que tout ce qui soit chargé dans le contexte de charge de réflexion uniquement est implémenté de manière à ne pas pouvoir déclencher accidentellement le chargement de l'assemblage dans l'appdomain actuel. Réfléchir sur les types d'attributs personnalisés définis dans l'assembly est l'un d'entre eux.

Vous auriez besoin d'utiliser CustomateTtributeTata ​​code> pour afficher ces attributs personnalisés. P>

var assy = Assembly.ReflectionOnlyLoadFrom("MuhPlugin.dll");
// gets assembly-level attributes, but you get the idea
var attrs = CustomAttributeData.GetCustomAttributes(assy);


0 commentaires