2010-09-09 6 views
6

Je sais qu'il est possible de charger dynamiquement des modules xap en utilisant le framework Prism ou MEF. Cependant, j'aimerais ne pas utiliser ces cadres. au lieu de charger mes fichiers xap manuellement. Donc, j'ai créé la classe suivante (adaptée d'Internet):silverlight 4, chargement dynamique de modules xap

public class XapLoader 
{ 
    public event XapLoadedEventHandler Completed; 

    private string _xapName; 

    public XapLoader(string xapName) 
    { 
     if (string.IsNullOrWhiteSpace(xapName)) 
      throw new ArgumentException("Invalid module name!"); 
     else 
      _xapName = xapName; 
    } 

    public void Begin() 
    { 
     Uri uri = new Uri(_xapName, UriKind.Relative); 
     if (uri != null) 
     { 
      WebClient wc = new WebClient(); 
      wc.OpenReadCompleted += onXapLoadingResponse; 
      wc.OpenReadAsync(uri); 
     } 
    } 

    private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e) 
    { 
     if ((e.Error == null) && (e.Cancelled == false)) 
      initXap(e.Result); 

     if (Completed != null) 
     { 
      XapLoadedEventArgs args = new XapLoadedEventArgs(); 
      args.Error = e.Error; 
      args.Cancelled = e.Cancelled; 
      Completed(this, args); 
     } 
    } 

    private void initXap(Stream stream) 
    { 
     string appManifest = new StreamReader(Application.GetResourceStream(
     new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml", 
             UriKind.Relative)).Stream).ReadToEnd(); 

     XElement deploy = XDocument.Parse(appManifest).Root; 

     List<XElement> parts = (from assemblyParts in deploy.Elements().Elements() 
           select assemblyParts).ToList(); 

     foreach (XElement xe in parts) 
     { 
      string source = xe.Attribute("Source").Value; 
      AssemblyPart asmPart = new AssemblyPart(); 
      StreamResourceInfo streamInfo = Application.GetResourceStream(
       new StreamResourceInfo(stream, "application/binary"), 
       new Uri(source, UriKind.Relative)); 
      asmPart.Load(streamInfo.Stream); 
     } 
    } 
} 

public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e); 

public class XapLoadedEventArgs : EventArgs 
{ 
    public Exception Error { get; set; } 

    public bool Cancelled { get; set; } 
} 

Le code ci-dessus fonctionne très bien; Je peux charger une XAP de la façon suivante:

XapLoader xapLoader = new XapLoader("Sales.xap"); 
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed); 
xapLoader.Begin(); 

Maintenant, j'ai un UserControl appelé InvoiceView dans le projet Sales.xap, donc je voudrais instancier la classe. Dans le projet en cours (Main.xap) j'ai ajouté une référence au projet Sales.xap, cependant, puisque je le charge manuellement, je définis "Copy Local = False". Mais lorsqu'il est exécuté, le code suivant lance TypeLoadException:

Sales.InvoiceView view = new Sales.InvoiceView(); 

Il semble que le Code ne peut pas trouver la classe InvoiceView. Mais j'ai vérifié que la méthode initXap() de XapLoader était exécutée avec succès. Alors pourquoi le code ne peut pas trouver la classe InvoiceView? Quelqu'un peut-il m'aider avec ce problème?

+0

Un moyen plus facile d'y parvenir est d'utiliser le MEF (Managed Extensibility Framework) intégré à Silverlight 4, en plus de .NET 4. –

Répondre

1

Ceci est basé sur l'auto-réponse du demandeur ci-dessous, plutôt que sur la question.

Si vous supprimez un projet/module, les fichiers de sortie/fichiers XAP sont conservés. Si vous cliquez sur le bouton "Afficher tous les fichiers", vous verrez certains fichiers de sortie restants dans vos dossiers clientbin, bin et obj de projets connexes.

alt text

Vous pouvez les supprimer individuellement du projet, ou, en cas de doute, chercher tous BIN et OBJ (par exemple en utilisant l'explorateur de fichiers) et de supprimer tous les dossiers. Les dossiers BIN/CLIENTBIN/OBJ seront recréés en cas de besoin (c'est le travail que l'option "clean" de Visual Studio aurait dû faire!)

J'espère que cela vous aidera.

+0

J'ai choisi votre réponse comme correcte, cependant, j'ai remarqué que le menu Build-> Clean de Visual Studio n'a pas aidé.La suppression des dossiers bin/obj peut aider (je ne l'ai pas encore fait), je ne veux pas faire Donc, actuellement, ce que je fais est de changer le numéro de port du serveur Web.En passant, ce problème arrive si souvent, même lorsque je n'ai rien renommé. – synergetic

1

Ok, j'ai trouvé la cause. Le code ci-dessus fonctionne. Après avoir créé un nouveau projet Silverlight (Sales.xap), il m'est arrivé de compiler ma solution une fois. J'ai ensuite supprimé la classe App dans Sales.xap et renommé la classe MainPage par défaut en SalesView. Cependant, peu importe le nombre de fois que j'ai compilé ma solution, le serveur Web de développement de Visual Studio chargeait la première version de Sales.xap (d'où?), Mon code n'a donc pas pu trouver SalesView. Dans mon projet hôte Asp.Net, j'ai défini le port du serveur de développement sur un numéro de port différent, et le problème a disparu. Donc, le problème était avec le serveur de développement de Visual Studio. Apparemment, il garde les fichiers xap compilés dans un dossier temporaire et ne met pas toujours à jour ces fichiers xap lorsque le code source a changé.

+0

J'avais le même problème, j'utilisais chrome - @Xds a raison .Les problèmes semblent être avec les fichiers xap de mise en cache de chrome grand temps! Si vous ouvrez une fenêtre de navigation privée pour la même URL, vous verrez les dernières modifications (puisque l'incognito ne cache pas). De plus, si vous utilisez IExplorer pour le même URL, il affichera le dernier - il ne cache pas non plus. On peut espérer que google chrome ne cache pas le xap de manière aussi rigide. :( – DeeStackOverflow

0

Ce que je fais pour éviter de tels problèmes lors de l'exécution fraîchement compilé Silverlight est clair que le cache du navigateur, chrome a même un cache de silverlight clair;)

0

ce XAP phénomènes de cache est souvent dû au studio visuel serveur Web intégré (Serveur de développement ASP.NET). Arrêtez simplement l'apparition de ce serveur et le cache sera effacé. Redémarrez votre projet et la dernière version de votre xap est appelée.

Questions connexes