2010-09-09 15 views
6

Ich weiß, dass es möglich ist, XAP-Module dynamisch mit Prism oder MEF-Framework zu laden. Allerdings möchte ich diese Frameworks nicht verwenden; Laden Sie stattdessen meine xap-Dateien manuell. Also, ich habe die folgende Klasse (aus dem Internet) erstellt:silverlight 4, dynamisch laden xap-Module

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; } 
} 

Der obige Code funktioniert gut; Ich kann jede xap die folgende Art und Weise laden:

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

Nun, ich habe einen Usercontrol InvoiceView im Sales.xap Projekt genannt, so mag ich die Klasse instanziiert. Im aktuellen Projekt (Main.xap) habe ich einen Verweis auf das Sales.xap-Projekt hinzugefügt, da ich es jedoch manuell lade, setze ich "Copy Local = False". Aber wenn sie ausgeführt werden, wirft der folgende Code Type:

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

Es scheint, den Code nicht InvoiceView Klasse finden. Aber ich habe überprüft, dass die initXap() -Methode von XapLoader erfolgreich ausgeführt wurde. Warum kann der Code die InvoiceView-Klasse nicht finden? Kann mir jemand bei diesem Problem helfen?

+0

Eine einfachere Möglichkeit, dies zu tun, ist die Verwendung des Managed Extensibility Framework (MEF), das in Silverlight 4 zusätzlich zu .NET 4 integriert ist. –

Antwort

1

Dies basiert auf der Antwort des Fragestellers unten, anstatt der Frage.

Wenn Sie ein Projekt/Modul löschen, hängen die Ausgabe-DLLs/XAP-Dateien herum. Wenn Sie auf die Schaltfläche "Alle Dateien anzeigen" klicken, sehen Sie einige dieser übriggebliebenen Ausgabedateien in Ihrem Ordner clientbin, und obj Ordner von verwandten Projekten.

alt text

Sie können sie aus dem Projekt gelöscht werden einzeln oder, im Zweifelsfall für alle BIN und OBJ suchen (zum Beispiel Desktop-Explorer) und alle diese Ordner löschen. Die BIN/CLIENTBIN/OBJ-Ordner werden bei Bedarf neu erstellt (dies ist der Job, den die "clean" -Option in Visual Studio hätte ausführen sollen!)

Hoffe, das hilft.

+0

Ich wählte Ihre Antwort als richtig, jedoch bemerkte ich, dass Visual Studio Build-> Clean-Menü nicht half. Das Löschen von bin/obj Ordner kann helfen (ich habe es noch nicht getan), ich will einfach nicht tun Das ist zur Zeit das, was ich gerade tue, die Portnummer des Webservers zu ändern. Übrigens passiert dieses Problem so oft, selbst wenn ich nichts umbenannt habe. – synergetic

1

Ok, ich habe die Ursache gefunden. Der obige Code funktioniert. Nach dem Erstellen eines neuen Silverlight-Projekts (Sales.xap) habe ich meine Lösung einmal kompiliert. Dann löschte ich App-Klasse in der Sales.xap und umbenannt Standard-MainPage-Klasse nach SalesView. Unabhängig davon, wie oft ich meine Lösung kompiliere, hat der Entwicklungswebserver von Visual Studio die erste Version von Sales.xap geladen (wo?), Sodass mein Code SalesView nicht finden konnte. In meinem Asp.Net-Host-Projekt habe ich den Port des Entwicklungsservers auf eine andere Portnummer gesetzt, und das Problem ist verschwunden. Das Problem lag also beim Entwicklungsserver von Visual Studio. Anscheinend speichert es kompilierte xap-Dateien in einem temporären Ordner und aktualisiert diese xap-Dateien nicht immer, wenn sich der Quellcode ändert.

+0

Ich hatte das gleiche Problem, ich war mit Chrom - @ Xds ist richtig .Die Probleme scheinen mit Chrome-Caching-XAP-Dateien große Zeit zu sein! Wenn Sie ein Inkognito-Fenster für dieselbe URL öffnen, werden die letzten Änderungen angezeigt (da das Inkognito nicht zwischengespeichert wird). Wenn Sie IEExplorer für die gleiche URL verwenden, wird auch die neueste Version angezeigt - sie wird auch nicht zwischengespeichert. Man würde hoffen, dass google chrome den xap nicht so starr zwischenspeichert. :( – DeeStackOverflow

0

Was ich tue, um solche Probleme zu vermeiden, wenn es frisch zusammengestellt Ausführen Silverlight klar ist die Browser-Cache, Chrom hat auch eine klare Silverlight-Cache;)

0

diese XAP Cache Phänomene auf den Visual Studio integrierten Web-Server ist oft durch (ASP.NET Entwicklungsserver). Stoppen Sie einfach das Auftreten dieses Servers und der Cache wird gelöscht. Starten Sie erneut Ihr Projekt und der neueste Build Ihres xap wird aufgerufen.