Chargement d’assembly externe en Silverlight 2

Quand une application commence à grossir en Silverlight c’est un seul et même fichier qui grossi. L’idée de ce billet est de montrer comment on peut découper l’application Silverlight en plusieurs XAP et de permettre un chargement différé des assembly contenant, ou des DLL, ou des ressources.

Il faut dans un premier temps découper l’application en Library:

image

Ici on a une class “ClassExternal” avec une methode “Somme”

 namespace SilverlightLibraryExternal
{
    public class ClassExternal
    {
        public int Somme(int i, int j)
        {
            return i + j;
        }
    }
}

Puis, de l’application Silverlight il faut référencer la library “SilverlightClassLibrary” mais avec l'option “Copy local” à False

Ce qui permet d’avoir accès a l’espace de nom pour la compilation mais de pas intégrer la Dll dans le XAP de l’application finale.

image image

Il faut donc charger la Dll au moment de l’exécution. Mais le mieux, c’est d’encapsuler cette Dll dans un zip (un fichier XAP) pour respecter le packaging de Silverlight 2.

Pour ce faire on peut utiliser plusieurs utilitaire j’ai pris “Chiron.exe” qui est dans le SDK de la DLR ici : https://www.codeplex.com/sdlsdk

J’ai donc rajouter 2 directives de post-compilation du projet “SilverlightLibraryExtenal”

image

 "C:\Program Files\Microsoft SDKs\Silverlight\sdlsdk\bin\Chiron.exe" /x:$(TargetName).xap
copy "$(TargetName).xap" "$(SolutionDir)SilverlightApplicationLoadExternalAssembly.Web\ClientBin\"

Ce qui donne après compilation dans le répertoire ClientBin deux fichiers XAP

image 

Passons au chargement dynamique de cette library:

La class StreamRessourceInfo permet de lire le contenu du XAP et la class AssemblyPart permet de charger un library dynamiquement.

L’option “NoInlining” de l’attribut “MethodImpl” spécifie que la méthode ne peut pas être “inlined” dans cette méthode il ne faut pas faire référence au Type externe, d’où l’utilisation de la méthode UseLibraryExternal qui fait simplement un Cast.

Une fois que tout ceci est fait on peut activer le bouton qui fait simplement un appel à la methode “Somme” l’avantage c’est que le développeur a l’aide à la saisie au moment du développement et aussi la vérification de type au moment de la compilation. On a simplement différé le chargement de l’assembly.

 

 public partial class Page : UserControl
{
    ClassExternal ext;
    public Page()
    {
        InitializeComponent();            
        //Chargement du XAP 
        WebClient wc = new WebClient();
        wc.OpenReadCompleted += 
              new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
        wc.OpenReadAsync(new Uri("SilverlightLibraryExternal.xap", 
                                 UriKind.Relative));
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(ext.Somme(2, 2).ToString());
    }

    void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        StreamResourceInfo zip = new StreamResourceInfo(e.Result, null);
        //Extration de la DLL du ZIP 
        StreamResourceInfo manifestInfo =
            Application.GetResourceStream(zip, 
               new Uri("SilverlightLibraryExternal.dll", UriKind.Relative));

        AssemblyPart part = new AssemblyPart();
        //Chargement de l’assembly 
        Assembly a = part.Load(manifestInfo.Stream);

        object o = CreateSLClassLibraryExternal();
        UseLibraryExternal(o);
        //Activation du bouton 
        bt1.IsEnabled = true;

    }

    //Methode non linker statiquement         
    [System.Runtime.CompilerServices.MethodImpl 
        (System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
    private object CreateSLClassLibraryExternal()
    {
        return new SilverlightLibraryExternal.ClassExternal();
    }

    private void UseLibraryExternal(Object o)
    {
        ext = (ClassExternal)o;
    }
}

Ce qui donne bien deux chargement de XAP :

image

Et le résultat attendu

image

Source du projet

Source : Cool Silverlight Trick #3, Downloading Zipped files with the WebClient, MSDN MethodImplAttributes Enumeration