Silverlight 动态加载XAP文件
本文根据网上资源整理而成,主要讲述两种动态加载Silverlight生成后的XAP文件的方法,实现按需下载减小传输文件的目的。
前置说明:
本文例子用VS2012编写,解决方案中有三个项目,一个Web应用程序,两个Silverlight应用程序(不是类库,类库在生成时默认不会生成独立的XAP包),如下图
1、方法一,直接将需要的XAP文件下载到本地内存
说明:这种方式,每次从服务器获得的XAP文件都是最新的,如果服务器端的XAP文件有所更改,客户端也会马上显示出来
根据例子来讲解,SlLogin.xap是程序运行时默认加载的XAP文件,SilverlightPartXap.xap是点击SlLogin项目中Login页面上的登录按钮后加载的XAP文件,并将新加载的XAP文件中的UI界面显示出来,Login.xaml后台主要源码如下(Login.cs):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;
using System.Xml.Linq;
namespace SlLogin
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
//登录
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
Uri mainXapUri = new Uri("SilverlightPartXap.xap",UriKind.Relative);
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += webClient_OpenReadCompleted;
webClient.OpenReadAsync(mainXapUri);//获取另一个xap文件
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
Stream mainXapStream = e.Result;
Assembly mainAssembly = LoadAssemblyFromXap(mainXapStream, "SilverlightPartXap.dll");
UIElement mainFrame = mainAssembly.CreateInstance("SilverlightPartXap.MainPage") as UIElement;
this.Content = mainFrame;
}
/// <summary>
/// 从XAP中获取程序集
/// </summary>
/// <param name="packageStream"></param>
/// <param name="assemblyName"></param>
/// <returns></returns>
Assembly LoadAssemblyFromXap(Stream packageStream, String assemblyName)
{
Stream stream = Application.GetResourceStream(
new StreamResourceInfo(packageStream, null),
new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
String appManifestString = new StreamReader(stream).ReadToEnd();
//Linq to xml
XElement deploymentRoot = XDocument.Parse(appManifestString).Root;
List<XElement> deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
select assemblyParts).ToList();
Assembly asm = null;
foreach (XElement xElement in deploymentParts)
{
string source = xElement.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
asmPart.Source = source;
StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(packageStream, "application/binary"), new Uri(source, UriKind.Relative));
if (source == "SilverlightPartXap.dll")
{
asm = asmPart.Load(streamInfo.Stream);
}
else
{
asmPart.Load(streamInfo.Stream);
}
}
return asm;
}
}
}
2.方法二,使用silverlight的独立存储区来存放从服务器动态加载的XAP文件,这样只要独立存储区的内容还存在,它就会使用独立存储区的内容,而不去从服务器重新加载,但得不到新的XAP,一旦服务器的XAP修改了,也不会立马显示,源码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;
using System.Xml.Linq;
namespace SlLogin
{
public partial class NLogin : UserControl
{
public NLogin()
{
InitializeComponent();
}
//登录
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
using (var store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.FileExists("SilverlightPartXap.xap"))
{
WebClient c = new WebClient();
c.OpenReadCompleted += new OpenReadCompletedEventHandler(c_OpenReadCompleted);
c.OpenReadAsync(new Uri("SilverlightPartXap.xap", UriKind.Relative));
}
else
{
LoadData();
}
}
}
void c_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (var store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
System.IO.IsolatedStorage.IsolatedStorageFileStream fileStream;
// create the file
fileStream = store.CreateFile("SilverlightPartXap.xap");
// write out the stream to isostore
WriteStream(e.Result, fileStream);
fileStream.Close();
}
LoadData();
}
private void WriteStream(Stream stream, System.IO.IsolatedStorage.IsolatedStorageFileStream fileStream)
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
fileStream.Write(buffer, 0, bytesRead);
}
}
private void LoadData()
{
using (var store = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream fileStream = store.OpenFile("SilverlightPartXap.xap", FileMode.Open, FileAccess.Read);
#region Original Code
StreamResourceInfo sri = new StreamResourceInfo(fileStream, "application/binary");
Stream manifestStream = Application.GetResourceStream(sri, new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
string appManifest = new StreamReader(manifestStream).ReadToEnd();
//Linq to xml
XElement deploymentRoot = XDocument.Parse(appManifest).Root;
List<XElement> deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
select assemblyParts).ToList();
Assembly asm = null;
foreach (XElement xElement in deploymentParts)
{
string source = xElement.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
asmPart.Source = source;
StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri(source, UriKind.Relative));
if (source == "SilverlightPartXap.dll")
{
asm = asmPart.Load(streamInfo.Stream);
}
else
{
asmPart.Load(streamInfo.Stream);
}
}
UIElement myData = asm.CreateInstance("SilverlightPartXap.MainPage") as UIElement;
this.Content = myData;
#endregion
}
}
}
}
浙公网安备 33010602011771号