Frédéric Colin
Framework .NET 2.0 et Reflection-Only
Parmi les très nombreux services offerts par le Framework .NET 2.0, une nouvelle fonctionnalité est apparue au niveau de la Réflexion .NET. Il s'agit du chargement d'assemblage dans un contexte Reflection-Only
Par Frédéric Colin publié le 07/11/2006 à 13:43, lu 10640 fois,
Le mode « Reflection-Only » permet le chargement d'une assembly en un mode où il est impossible d'en exécuter le code. Une sorte d'accès « Read-Only » pour simplifier. Mais en quoi est-ce intéressant me direz-vous par rapport à ce qui existait avant ? Simplement utile pour ces deux raisons :
  • Le chargement est plus rapide
  • La sécurité n'est pas évaluée
Les méthodes partagées suivantes ont donc été ajoutées à la classe Assembly :
  • Assembly.ReflectionOnlyLoad(...)
  • Assembly.ReflectionOnlyLoadFrom(...)
Par contre, cette manière de faire apporte notamment les inconvénients suivants :
  • Pas d'exécution possible sur l'assembly chargée
  • Dépendances avec d'autres assemblies non chargées automatiquement
  • Chargement à partir d'un chemin ou d'un tableau d'octets uniquement
Vous l'aurez compris la problématique qui m'importe sera le chargement des assemblies dépendantes. Tel quel, le message d'erreur est le suivant :
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Lorsque l'on examine en détail l'exception :
 
Détail de l'erreur précédente

Détail de l'erreur précédente

 
Cette problématique peut-être facilement solutionnée grâce à l'événement « ReflectionOnlyAssemblyResolve » qui est levé sur l'AppDomain courant à chaque fois qu'une assembly dépendante est manquante dans le contexte Reflection-Only. Voici un exemple qui permet de charger et de parcourir l'assembly courante :

Imports System.Reflection

Imports System.IO

Module Module1

    Private WithEvents appD As AppDomain = AppDomain.CurrentDomain

 

    Private Sub Display(ByVal s As String, ByVal left As Int32, ByVal color As ConsoleColor)

        Console.CursorLeft = left

        Console.ForegroundColor = color

        Console.WriteLine(s)

    End Sub

 

    Sub Main()

        Dim assemb As Assembly = Nothing

 

        Try

            ' Chargement de l'assembly en mode Reflection-Only

            assemb _

                = Assembly.ReflectionOnlyLoadFrom(Path.GetFileName(Assembly.GetExecutingAssembly().Location))

 

            ' Parcours des types

            For Each item As Type In assemb.GetTypes()

                Display(item.FullName, 0, ConsoleColor.DarkRed)

 

                ' Parcours des membres

                For Each m As MemberInfo In item.GetMembers()

                    Display(m.Name, 4, ConsoleColor.DarkGreen)

                Next

            Next

        Catch ex As ReflectionTypeLoadException

            Console.WriteLine(ex.ToString)

        Catch ex As Exception

            Console.WriteLine(ex.ToString)

        Finally

            Console.ReadLine()

        End Try

    End Sub

 

    Private Function appD_ReflectionOnlyAssemblyResolve(ByVal sender As Object, ByVal args As System.ResolveEventArgs) _

    As System.Reflection.Assembly Handles appD.ReflectionOnlyAssemblyResolve

        Return Assembly.ReflectionOnlyLoad(args.Name)

    End Function

End Module

Par contre, il est dommage que le mode « Reflection-Only » ne solutionne pas le déchargement de l'assembly. En effet, il n'existe toujours pas de « Unload » et l'on doit encore passer par un AppDomain dédié si l'on souhaite décharger une assembly. Mais c'est une autre histoire ...
Enjoy!
 
» Démarrer une discussion