Silverlight Xap包、配置文件修改后不能自动更新问题处理方式总结

时间:2022-11-03 05:57:24

普遍的做法是给Xap包、配置文件增加版本号控制。

Xap包、配置文件的版本可以通过配置文件记录,但是需要在项目更新时,更新此文件,对于规模比较大的项目(Xap包比较多) ,升级、维护也存在困难。如果配置文件的版本也放到版本控制的文件中,维护工作量会很大。鉴于此,我们可以采取以下方案:

1.Xap包、配置文件版本文件由程序自动更新。 

 以Asp.net为例:

可以在Global.asax 中增加监测Xap文件修改记录,如果有修改,则自动更新版本记录文件或更新记录文件版本的变量,代码如下:            

        string xapFilePath =Server.MapPath("Clientbin");
            if (System.IO.Directory.Exists(xapFilePath))
            {
                System.IO.FileSystemWatcher xapFileWatcher = new System.IO.FileSystemWatcher(xapFilePath, "*.xap");
                Application["XapFileWatcher"] = xapFileWatcher;
                //设置监测的文件修改类型
                xapFileWatcher.NotifyFilter = System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.CreationTime | System.IO.NotifyFilters.Size;
                xapFileWatcher.Created += xapFileWatcher_Changed;
                xapFileWatcher.Changed += xapFileWatcher_Changed;
                xapFileWatcher.Deleted += xapFileWatcher_Changed;
                xapFileWatcher.Renamed += xapFileWatcher_Changed;
                xapFileWatcher.EnableRaisingEvents = true;
            }

 

   /// <summary>
    /// 检测到文件更新,更新文件版本
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void xapFileWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
    {
        GetFileInfo();
    }
 private void GetFileInfo()
    {
        List<String> fileList = new List<string>();
        string serverPath = GetFilePath();
        if (System.IO.Directory.Exists(serverPath))
        {
            System.IO.DirectoryInfo ClientBinInfo = new System.IO.DirectoryInfo(serverPath);
            foreach (System.IO.FileInfo xapFile in ClientBinInfo.GetFiles("*.xap"))
            {
                string fileName = xapFile.Name;
                //我们这里采用文件修改时间作为版本标识
                string modifyTime = xapFile.LastWriteTime.ToString("yyyyMMddHHmmss");
                fileList.Add(string.Format("{0},{1}", fileName, modifyTime));
            }
        }
        string file = System.IO.Path.Combine(serverPath, "XapVar.xml");
        SaveVerToFile(fileList, file);
    }
    /// <summary>
    /// 序列化,保存
    /// </summary>
    /// <param name="aObject"></param>
    /// <param name="fileName"></param>
    /// <returns></returns>
    private void SaveVerToFile(object aObject, string fileName)
    {
        using (System.IO.FileStream fs = System.IO.File.Open(fileName, System.IO.FileMode.Create))
        {
            var serializer = new System.Runtime.Serialization.DataContractSerializer(aObject.GetType());
            serializer.WriteObject(fs, aObject);
            fs.Close();
        }
    }

这种方式可以做到自动监测,自动更新,不需要手工参与。版本更新可以采用上面的更新文件的方式(记住给目标目录开通读写权限),也可以通过Silverlight的InitParameter传递给Silverlight端控制。

至于Silverlight端接收到文件版本,可以通过在Uri后加版本参数的方式,控制浏览器使用更新后的Xap或配置文件。例如:  

TextApp.xap?201301231551

增加参数的方式可以在各模块单独加,也可以封装一个公共处理模块负责读取文件、更新版本。还有一种处理方式,可以一次性解决版本问题,即重写WebRequest创建者,代码如下:  

    /// <summary>
    /// 创建WebRequest,并根据版本号更新请求Url
    /// </summary>
    internal class BrowserHttpWebRequestCreator : System.Net.IWebRequestCreate
    {
        string mSysVar = "0";
        public BrowserHttpWebRequestCreator(string sysVar)
        {
            mSysVar = sysVar;
        }
        public System.Net.WebRequest Create(Uri uri)
        {
            if (uri != null)
            {
                string uriStr = uri.OriginalString;
                if (uriStr.IndexOf("?") == -1)
                {
                    uriStr = uriStr + string.Format("?{0}", mSysVar);
                    uri = new Uri(uriStr, UriKind.RelativeOrAbsolute);
                }
            }
            return System.Net.Browser.WebRequestCreator.BrowserHttp.Create(uri);
        }
    }

使用下面的代码指定Silverlight使用我们的Creator:  

       BrowserHttpWebRequestCreator browserHttpWebRequestCreator = new IMG.Startup.BrowserHttpWebRequestCreator(版本号);
            System.Net.WebRequest.RegisterPrefix("http://", browserHttpWebRequestCreator);
            System.Net.WebRequest.RegisterPrefix("https://", browserHttpWebRequestCreator);

对于已经开发完毕的系统,要增加版本控制能力,也可以采用这种方式。只需要在App中增加这部分处理就可以,不需要修改现有模块。

ps:上面的代码是版本统一控制,如果针对不同文件控制,修改相应逻辑即可。