• 取经之旅——把WinForms开发的桌面应用移植到Silverlight开发的RIA(第1部分)


    1,SerializableAttribute不存在

    在Silverlight中,已经不包含SerializableAttribute,不过没有了这个标记也不会影响序列化。去除这个特性标记的原因,是因为已经了一系列XML为开头的用于序列化的特性标记。

    对于这个变动,没有什么难点,主要是比较麻烦,需要逐一删除。当然如果不想删除,最简单的方式就是,自己创建一个SerializableAttribute 。

    2,Dictionary的xml序列化,用XElement代替XmlDocument,Convert.ChangeType的参数变化

    说起来,就是不在Silverlight中,也没有办法用XmlSerializer对Dictionary<>进行序列化。而我直接实现了一个能够Xml序列化的Dictionary,代码如下:

     public class XmlSerDictionary<TKey, Tvalue> : Dictionary<TKey, Tvalue>, IXmlSerializable
        {
            #region IXmlSerializable Members
    
            System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
            {
                return null;
            }
    
            void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(reader.ReadOuterXml());
    
                foreach (XmlElement item in doc.ChildNodes[0].ChildNodes)
                {
                    TKey key = (TKey)Convert.ChangeType(item.GetAttribute("key"), typeof(TKey));
                    Tvalue value = (Tvalue)Convert.ChangeType(item.InnerText, typeof(Tvalue));
                    this.Add(key, value);
                }
            }
    
            void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
            {
                foreach (var item in this)
                {
                    writer.WriteStartElement("item");
                    writer.WriteAttributeString("key", item.Key.ToString());
                    writer.WriteValue(item.Value);
                    writer.WriteEndElement();
                }
            }
    
            #endregion
        }

    但是在ReadXml方法中,我之前使用XmlDocument,这个东西在Silverlight中已经不存在,只能用XDocument或XElement代替,新的代码如下:

            void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
            {
                XElement ele = XElement.Parse(reader.ReadOuterXml());
                foreach (var item in ele.Descendants())
                {
                    TKey key = (TKey)Convert.ChangeType(item.Attribute("key").Value, typeof(TKey), null);
                    Tvalue value = (Tvalue)Convert.ChangeType(item.Value, typeof(Tvalue),null);
                    this.Add(key, value);
                }
            }
    

    当然,如果不是要兼容之前的Xml序列化的文件,完全可以用DataContact对Dictionary<>直接进行序列化(甚至还可以支持JSON)

    注意上述修改的代码,我们发现Convert.ChangeType的参数也发生了变化,在之前Convert.ChangeType这个方法支持2个参数,而在Silverlight中只支持3个参数,所以最后要传入null。

    从这个细节,可以看出微软为了缩减Silverlight的大小不予余力,精简到每个方法。

    3,List<T>的Find方法不存在

    Find是LINQ出现之前就提供的扩展方法,而Silverlight再次为了缩减大小,把类似的一些扩展方法也去除了。为了不对原有代码造成太大的改动,我只好自己实现了Find方法,如下:

            public static T Find<T>(this IEnumerable<T> list, Func<T, bool> comparison)
            {
                foreach (T item in list)
                {
                    if (comparison(item))
                    {
                        return item;
                    }
                }
                return default(T); 
            }
    

    当然,也可以用First扩展方法来代替。

    4,Directory.GetFiles方法变为EnumerateFiles,GetDirectories变为EnumerateDirectories

    这个改变,主要原因是通过EnumerateFiles返回IEnumerable<string>而非之前的GetFiles方法的string[]。由于有一个地方必须使用string[],不然就会对代码造成很大影响,所以只好实现了自己的方法:

            public static string[] GetFiles(string dir)
            {
                var names = Directory.EnumerateFiles(dir);
                List<string> lst = new List<string>(names);
                return lst.ToArray();
            }
            public static string[] GetDirectories(string dir)
            {
                var names = Directory.EnumerateDirectories(dir);
                List<string> lst = new List<string>(names);
                return lst.ToArray();
            }

    当然,在大部分情况,还是建议直接使用EnumerateFiles方法和EnumerateDirectories方法。

    5,读写zip文件

    在.NET中可以通过System.IO.Compression命名空间来读写zip文件,当然也可以用SharpZipLib。

    在Silverlight中如果仅仅想读取zip文件的内容,可以把zip作为Content添加到xap中,然后用如下代码来读取其中的文件:

    var zipfile = Application.GetResourceStream(new Uri("LCADB/entries_ILCD.zip",UriKind.Relative));
    var xmlfile = Application.GetResourceStream(zipfile, new Uri("Locations_ILCD.xml",UriKind.Relative));
    List<Location> lst = SerializationHelper.FromXml<List<Location>>(xmlfile.Stream);
    

    用Application.GetResourceStream访问压缩文件的更详细的信息,见:

    http://www.silverlightexamples.net/post/How-to-Get-Files-From-Resources-in-Silverlight-20.aspx

    要写zip文件,就没有现成的函数库可用了,不过幸好有人把SharpZipLib移植到了Silverlight上,见:

    http://slsharpziplib.codeplex.com/

    分享到: 更多
  • 相关阅读:
    Linux基础-文件管理
    Linux基础-命令概述
    linux基础--目录介绍
    Cookie和Session(session过程和设置进程外session)
    [CSP-S2020]儒略日 题解
    [NOI2020]制作菜品 题解
    [NOI2020]命运 题解
    CSP-S2020 游记
    2020年泉州市信息学国庆模拟赛(提高组) 题解
    luogu4241 采摘毒瘤 题解
  • 原文地址:https://www.cnblogs.com/redmoon/p/1699925.html
Copyright © 2020-2023  润新知