【WP8】自定义配置存储类

之前在WP7升级到WP8的时候遇到配置不兼容的问题

情景:之前只有一个WP7版本,现在需要发布WP8版本,让用户可以从原来的WP7版本升级到WP8版本

  一般情况下从WP7升级到WP8没什么问题

  但是在项目中升级到WP8的时候,原先在WP7下保存在IsolatedStorageSettings的数据都不出来,经过调试发现

1、IsolatedStorageSettings存放数据的隔离存储控件的"__ApplicationSettings"文件中,存放的格式如下 {"test":"TestData"}

<ArrayOfKeyValueOfstringanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<KeyValueOfstringanyType>
<Key>test</Key>
<Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">TestData</Value>
</KeyValueOfstringanyType>
</ArrayOfKeyValueOfstringanyType>

2、但是原来的项目中使用了友盟WP7版本,后来的项目中使用的是WP8版本,友盟会向"__ApplicationSettings"文件中写入数据,如下:

UmengSDK.Business.OnlineConfigManager+OnlineConfig, UmengAnalyticsWP7, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
<ArrayOfKeyValueOfstringanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<KeyValueOfstringanyType>
<Key>test</Key>
<Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">TestData</Value>
</KeyValueOfstringanyType>
<KeyValueOfstringanyType>
<Key>device_id</Key>
<Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">0BBB2DF41DD5688A25517F2968339DC0</Value>
</KeyValueOfstringanyType>
<KeyValueOfstringanyType>
<Key>wp_device</Key>
<Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">1C43AC07795C55C2ADA78B0DD5A79B3660A7D137</Value>
</KeyValueOfstringanyType>
<KeyValueOfstringanyType>
<Key>config</Key>
<Value xmlns:d3p1="http://schemas.datacontract.org/2004/07/UmengSDK.Business" i:type="d3p1:OnlineConfigManager.OnlineConfig">
<d3p1:Interval>30</d3p1:Interval>
<d3p1:LastConfigTime>Wed Jul 02 00:43:35 CST 2014</d3p1:LastConfigTime>
<d3p1:Policy>BATCH_AT_LAUNCH</d3p1:Policy>
</Value>
</KeyValueOfstringanyType>
</ArrayOfKeyValueOfstringanyType>

3、而上面数据到了WP8上就不能正常读取原来存放的数据(如果在WP8项目中用WP7版的友盟则可以正常读取),导致原来存放的其他信息也读取不出来

4、下面试图自定义一个与 IsolatedStorageSettings 功能类似的类用于小数据的存取,避免第三方类库对"__ApplicationSettings"文件的修改导致一些兼容性问题

  IsolatedStorageSettings 存放的是键值对,也就是字典模型,我们需要把Dictionary序列化到文件中,但是Dictionary不支持直接序列化,先对Dictionary进行扩展,让其支持序列化

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization; namespace XTuOne.Common.Helpers
{
/// <summary>
/// 可序列化的Dictionary
/// </summary>
[XmlRoot("Dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
#region 构造函数,调用基类的构造函数 public SerializableDictionary()
{
} public SerializableDictionary(IDictionary<TKey, TValue> dictionary)
: base(dictionary)
{
} public SerializableDictionary(IEqualityComparer<TKey> comparer)
: base(comparer)
{
} public SerializableDictionary(int capacity)
: base(capacity)
{
} public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
: base(capacity, comparer)
{
} public SerializableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
: base(dictionary, comparer)
{
} #endregion #region IXmlSerializable 接口的实现 public XmlSchema GetSchema()
{
throw new NotImplementedException();
} /// <summary>
/// 从对象的XML表示形式生成该对象
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
var keySerializer = new XmlSerializer(typeof (TKey));
var valueSerializer = new XmlSerializer(typeof (TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read(); if (wasEmpty)
return;
while (reader.NodeType != XmlNodeType.EndElement)
{
reader.ReadStartElement("Key");
TKey key = (TKey) keySerializer.Deserialize(reader);
reader.ReadEndElement(); reader.ReadStartElement("Value");
TValue value = (TValue) valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.MoveToContent();
}
reader.ReadEndElement();
} /// <summary>
/// 将对象转换为其XML表示形式
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof (TKey));
var valueSerializer = new XmlSerializer(typeof (TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("Key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement(); writer.WriteStartElement("Value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
}
} #endregion
}
}

5、使用系统的Xml序列化功能保存数据

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Xml.Linq;
using System.Xml.Serialization; namespace XTuOne.Common.Helpers
{
public class XmlHelper
{
private XmlHelper()
{
} /// <summary>
/// 序列化对象到文件
/// </summary>
/// <param name="file">文件路径:"/test.xml"</param>
/// <param name="obj"></param>
public static void Serialize<T>(string file, T obj)
{
using (var sf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var fs = new IsolatedStorageFileStream(file, FileMode.OpenOrCreate, FileAccess.Write, sf))
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(fs, obj);
}
}
} /// <summary>
/// 反序列化文件到对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="file">文件路径:"/test.xml"</param>
public static T Deserialize<T>(string file)
{
using (var sf = IsolatedStorageFile.GetUserStoreForApplication())
{
var serializer = new XmlSerializer(typeof(T));
using (var fs = sf.OpenFile(file, FileMode.Open, FileAccess.Read))
{
return (T)serializer.Deserialize(fs);
}
}
} /// <summary>
/// 读取配置文件的信息
/// </summary>
/// <param name="file">前面不加/</param>
/// <param name="node">用.隔开(例如App.Version)</param>
/// <param name="attribute"></param>
public static string GetConfigValue(string file,string node, string attribute)
{
var configFile = Application.GetResourceStream(new Uri(file, UriKind.Relative));
return GetXmlValue(configFile.Stream, node, attribute);
} private static string GetXmlValue(Stream stream, string node, string attribute)
{
var configDoc = XDocument.Load(stream);
XElement temp = null;
foreach (var n in node.Split('.'))
{
if (temp == null)
{
temp = configDoc.Element(n);
continue;
}
temp = temp.Element(n);
} if (temp == null)
{
throw new NullReferenceException();
}
return temp.Attribute(attribute).Value;
} }
}

XmlHelper

// *************************************************
//
// 作者:bomo
// 小组:WP开发组
// 创建日期:2014/6/21 14:55:56
// 版本号:V1.00
// 说明:
//
// *************************************************
//
// 修改历史:
// Date WhoChanges Made
// 2014/6/21 14:55:56 bomo Initial creation
//
// ************************************************* using System.IO;
using System.IO.IsolatedStorage;
using XTuOne.Common.Helpers; namespace XTuOne.Utility.Helpers
{
/// <summary>
/// 自定义应用程序配置(相当于IsolatedStorageSetting)
/// </summary>
public class ApplicationSetting
{
/// <summary>
/// 保存配置的文件名
/// </summary>
private readonly string filePath; private readonly SerializableDictionary<string, object> dictionary; public ApplicationSetting(string filePath)
{
this.filePath = filePath;
//读取配置
using (var sf = IsolatedStorageFile.GetUserStoreForApplication())
{
var directory = Path.GetDirectoryName(filePath);
if (directory != null)
{
if (sf.DirectoryExists(directory))
{
sf.CreateDirectory(directory);
}
} dictionary = sf.FileExists(filePath)
? XmlHelper.Deserialize<SerializableDictionary<string, object>>(filePath)
: new SerializableDictionary<string, object>();
}
} /// <summary>
/// 通过索引赋值需要显式保存
/// </summary>
public object this[string key]
{
get { return Contains(key) ? dictionary[key] : null; }
set { dictionary[key] = value.ToString(); }
} public T Get<T>(string key)
{
return (T) dictionary[key];
} /// <summary>
/// 通过键获取值,如果不存在,则返回传入的默认值
/// </summary>
public T Get<T>(string key, T defaultValue)
{
return dictionary.ContainsKey(key) ? (T) dictionary[key] : defaultValue;
} /// <summary>
/// 设置值,自动保存
/// </summary>
public void Set(string key, object value)
{
if (dictionary.ContainsKey(key))
{
dictionary[key] = value;
}
else
{
dictionary.Add(key, value);
}
Save();
} /// <summary>
/// 保存配置到文件
/// </summary>
public void Save()
{
XmlHelper.Serialize(filePath, dictionary);
} /// <summary>
/// 判断是否包含键
/// </summary>
public bool Contains(string key)
{
return dictionary.ContainsKey(key);
} /// <summary>
/// 析构时保存数据
/// </summary>
~ApplicationSetting()
{
Save();
}
}
}

使用自定义的配置管理器可以控制文件信息,不会出现上述与第三方类库的一些兼容性问题(当然,这种情况比较少)

注意:该配置文件只支持基础类型,不支持复杂类型

上一篇:ASP.Net核心对象之HttpResponse


下一篇:django 生成复杂的 PDF 文件(数据较多时)