取经之旅——把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/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器