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
            }
        }
    }
} 
posted @ 2012-08-23 21:11  liancs  阅读(317)  评论(0编辑  收藏  举报