2010-09-09 18 views
6

Sé que es posible cargar módulos xap dinámicamente utilizando el marco Prism o MEF. Sin embargo, me gustaría no usar esos marcos; En su lugar, cargue mis archivos xap manualmente. Entonces, creé la siguiente clase (adaptada de internet):silverlight 4, cargando dinámicamente módulos 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; } 
} 

El código anterior funciona bien; Puedo cargar cualquier XAP de la siguiente manera:

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

Ahora, tengo un control de usuario llamada InvoiceView en el proyecto Sales.xap, así que me gustaría crear una instancia de la clase. En el proyecto actual (Main.xap) agregué referencia al proyecto Sales.xap, sin embargo, dado que lo cargo manualmente, configuro "Copiar local = falso". Sin embargo, cuando se ejecuta, el código siguiente lanza TypeLoadException:

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

Parece que el código no puede encontrar la clase InvoiceView. Pero comprobé que el método initXap() de XapLoader se ejecutó con éxito. Entonces, ¿por qué el código no puede encontrar la clase InvoiceView? ¿Puede alguien ayudarme con este problema?

+0

Una forma más fácil de hacerlo es utilizar el Marco de Extensibilidad Administrado (MEF) que está integrado en Silverlight 4, además de .NET 4. –

Respuesta

1

Esto se basa en la respuesta del autor de la pregunta a continuación, en lugar de la pregunta.

Si elimina un proyecto/módulo, los archivos DLL/XAP de salida se almacenan. Si hace clic en el botón "mostrar todos los archivos", verá algunos de estos archivos de salida sobrantes en su clientbin, bin y obj carpetas de proyectos relacionados.

alt text

Puede eliminar de forma individual desde el proyecto o, en caso de duda, la búsqueda de todos BIN y OBJ (por ejemplo, utilizando el explorador de escritorio) y eliminar todas esas carpetas. Las carpetas BIN/CLIENTBIN/OBJ se recrearán cuando sea necesario (este es el trabajo que debería haber hecho la opción "limpiar" en Visual Studio)

Espero que esto ayude.

+0

Elegí su respuesta como correcta, sin embargo, me di cuenta de que el menú Build-> Clean de Visual Studio no ayudó. Eliminar las carpetas bin/obj puede ayudar (no lo hice aún), simplemente no quiero hacer repetitivamente. Por lo tanto, actualmente lo que estoy haciendo es cambiar el número de puerto del servidor web. Por cierto, este problema ocurre con tanta frecuencia, incluso cuando no renombré nada. – synergetic

1

Bien, encontré la causa. El código anterior funciona. Después de crear un nuevo proyecto Silverlight (Sales.xap), una vez compilé mi solución. Luego borré App class en Sales.xap y cambié el nombre de la clase MainPage predeterminada a SalesView. Sin embargo, no importa cuántas veces compile mi solución, el servidor web de desarrollo de Visual Studio estaba cargando la primera versión de Sales.xap (¿desde dónde?), Por lo que mi código no pudo encontrar SalesView. En mi proyecto Asp.Net de host, establecí el puerto del servidor de desarrollo en un número de puerto diferente, y el problema desapareció. Entonces el problema fue con el servidor de desarrollo de Visual Studio. Aparentemente mantiene los archivos compilados xap en alguna carpeta temporal, y no siempre actualiza esos archivos xap cuando cambia el código fuente.

+0

Estaba teniendo el mismo problema, estaba usando Chrome - @Xds es correcto .¡Parece que los problemas son con los archivos xap de caché de Chrome a lo grande! Si abre una ventana de incógnito para la misma URL, verá los últimos cambios (dado que el incógnito no guarda en caché). Además, si usa IExplorer para la misma URL, mostrará la última; tampoco guarda en caché. Uno esperaría que Google Chrome no almacenara en caché el xap tan rígidamente. :( – DeeStackOverflow

0

Lo que hago para evitar este tipo de problemas al ejecutar recién compilado Silverlight es clara la caché del navegador, Chrome, incluso tiene un caché de Silverlight claro;)

0

este XAP caché fenómenos es a menudo debido a la Visual Studio servidor web incorporado (ASP.NET Development Server). Simplemente detenga la aparición de este servidor y la caché se borrará. Comience de nuevo su proyecto y se llama a la última compilación de su xap.

Cuestiones relacionadas