Modification des assemblages .NET existants
-
02-07-2019 - |
Question
Existe-t-il un moyen de modifier les assemblys .NET existants sans recourir à des outils tiers? Je sais que PostSharp rend cela possible, mais je trouve extrêmement pénible que le développeur de PostSharp ait essentiellement réécrit la fonctionnalité. de tout l'espace de noms System.Reflection
afin de rendre modifiables les assemblys existants.
System.Reflection.Emit
permet uniquement la création de nouveaux assemblys dynamiques. Cependant, toutes les classes de générateur utilisées ici héritent des classes de réflexion de base (par exemple, TypeBuilder
hérite de System.Type
). Malheureusement, il ne semble pas y avoir de moyen de contraindre un type existant chargé dynamiquement dans un constructeur de types. Au moins, il n'y a pas de manière officielle et soutenue.
Alors, qu'en est-il des non pris en charge? Est-ce que quelqu'un connaît des portes dérobées permettant de charger des assemblys ou types existants dans de telles classes de constructeurs?
Remarquez bien que je ne cherche pas à modifier l’assemblage en cours (cette peut même être une requête déraisonnable), mais simplement à modifier les assemblages existants chargés à partir du disque. Je crains qu'il n'y en ait pas, mais j'aimerais quand même demander.
Dans le pire des cas, il faudrait recourir à ildasm.exe
pour désassembler le code, puis à ilasm.exe
pour le réassemblage, mais aucune chaîne d'outils (lire: IL Reader) contenu dans .NET pour travailler avec les données IL (ou existe-t-il?).
/ EDIT:
Je n'ai pas de cas d'utilisation spécifique. Je suis simplement intéressé par une solution polyvalente, car la correction des assemblys existants est une tâche assez courante. Prenez des obfuscateurs par exemple, ou des profileurs, ou des bibliothèques AOP (oui, ces dernières peuvent être implémentées différemment). Comme je l'ai dit, il semble extrêmement inutile de devoir réécrire de grandes parties de l'infrastructure existante dans System.Reflection
.
@Wedge:
Vous avez raison. Cependant, il n'y a pas de cas d'utilisation spécifique ici. J'ai modifié la question initiale pour refléter cela. Une autre question a suscité mon intérêt. Le demandeur voulait savoir comment insérer les instructions pop
et ret
à la fin de chaque méthode afin de conserver le réflecteur de Lutz Roeder réingénierie du code source (VB ou C #).
Maintenant, ce scénario peut être réalisé avec un certain nombre d’outils, par exemple: PostSharp mentionné ci-dessus et le plug-in Reflexil pour Reflector, qui utilise à son tour le bibliothèque Cecil .
Dans l’ensemble, je ne suis pas satisfait du framework .NET.
@Joel:
Oui, je suis conscient de cette limitation. Merci quand même pour le signaler, car c'est important.
@marxidad:
Cela semble être la seule approche possible. Toutefois, cela signifierait que vous devrez toujours recréer l'assemblage complet à l'aide des classes de générateur, n'est-ce pas? C'est à dire. vous auriez à marcher sur l'ensemble de l'assemblage manuellement.
Hmm, je vais regarder ça.
La solution
Vous pouvez utiliser MethodInfo.GetMethodBody (). GetILAsByteArray () , modifiez cela, puis réenregistrez-le dans MethodBuilder.CreateMethodBody () .
Autres conseils
Mono.Cecil vous permet également de supprimer le nom fort d'un assemblage donné et de le sauvegarder en tant qu'assemblage non signé. Une fois que vous supprimez le nom fort de l'assembly, vous pouvez simplement modifier l'IL de votre méthode cible et utiliser l'assembly comme vous le feriez avec tout autre assembly. Voici le lien pour supprimer le nom fort avec Cecil:
Un point important: si l'ensemble est signé , toute modification échouera et vous obtiendrez un raté.
Les assemblys .NET Framework sont signés et, comme Joel Coehoorn l’a dit, vous obtiendrez un raté.
Vous pouvez charger l'assemblage à l'aide d'IronRuby et mélanger toutes les fonctionnalités dont vous pouvez rêver