【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
    }
}
View Code

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();
        }
    }
}

 

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

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

posted @ 2014-07-02 01:02  bomo  阅读(874)  评论(0编辑  收藏  举报