取经之旅——把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/

 

你可能感兴趣的:(silverlight)