使用.NET4.0的dynamic特性解析plist文件及json字符串

1.解析plist文件:

    using System;
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    using System.Dynamic;
    using System.Collections.Generic; 

    public class DynamicDictionary : DynamicObject
    {
        public IDictionary<string, object> Items;

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (Items == null || !Items.TryGetValue(binder.Name, out result)) result = null;
            if (result is DynamicDictionary) 
                result = (dynamic)result;
            return true;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (Items == null) Items = new Dictionary<string, object>();
            if (value is IDictionary<string, object>)
                value = new DynamicDictionary() { Items = (IDictionary<string, object>)value };
            else if (value is IEnumerable<IDictionary<string, object>>)
                value = from x in (IEnumerable<IDictionary<string, object>>)value select new DynamicDictionary() { Items = x };
            Items[binder.Name] = value;
            return true;
        }
    }

    /// <summary>plist文件解析器</summary>
    public class Plist : DynamicDictionary
    {
        public Plist() 
        {
            Items = new Dictionary<string, object>();
        }

        public Plist(string file)
        {
            var doc = XDocument.Load(file);

            Items = Parse(doc.Element("plist").Element("dict"));
        }

        private static IDictionary<string, object> Parse(XElement dict)
        {
            if (dict == null || dict.Name != "dict")
                throw new ArgumentException();

            var ret = new Dictionary<string, object>();
            var elements = dict.Elements().ToArray();
            for (int i = 0; i < elements.Length; i += 2)
            {
                var key = elements[i].Value;
                var node = elements[i + 1];
                switch (node.Name.LocalName)
                {
                    case "string":
                        ret[key] = node.Value;
                        break;
                    case "real":
                    case "integer":
                        ret[key] = int.Parse(node.Value.Trim());
                        break;
                    case "true":
                        ret[key] = true;
                        break;
                    case "false":
                        ret[key] = false;
                        break;
                    case "date":
                        ret[key] = DateTime.Parse(node.Value.Trim());
                        break;
                    case "data":
                        ret[key] = Convert.FromBase64String(node.Value.Trim());
                        break;
                    case "array":
                        ret[key] = from n in node.Elements() select new DynamicDictionary() { Items = Parse(n) };
                        break;
                    case "dict":
                        ret[key] = new DynamicDictionary() { Items = Parse(node) };
                        break;
                    default:
                        throw new NotSupportedException();
                }
            }
            return ret;
        }

        private static XElement Save(IDictionary<string, object> dict) 
        {
            var node = new XElement("dict");
            foreach (var kv in dict) 
            {
                node.Add(new XElement("key", kv.Key));
                if (kv.Value is string)
                    node.Add(new XElement("string", kv.Value));
                else if (kv.Value is int)
                    node.Add(new XElement("integer", kv.Value));
                else if (kv.Value is bool)
                    node.Add(new XElement(kv.Value.ToString()));
                else if (kv.Value is DateTime)
                    node.Add(new XElement("date", kv.Value));
                else if (kv.Value is byte[])
                    node.Add(new XElement("data", Convert.ToBase64String((byte[])kv.Value)));
                else if (kv.Value is DynamicDictionary)
                    node.Add(Save(((DynamicDictionary)kv.Value).Items));
                else if (kv.Value is IEnumerable<DynamicDictionary>)
                    node.Add(new XElement("array", from x in (IEnumerable<DynamicDictionary>)kv.Value select Save(x.Items)));
            }
            return node;
        }

        public void Save(string file) 
        {
            using (var stream = File.Open(file, FileMode.Create, FileAccess.Write, FileShare.None))
                Save(stream);
        }

        public void Save(Stream stream)
        {
            var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), new XElement("plist", Save(Items)));
            doc.Save(stream);
        }
    }

  使用方法:

dynamic plist = new Plist(file); //加载plist文件
string key = (string)plist.Key;  //获取值
if(plist.Name == null)               //等于null表示plist文件中不包含节点Name
{
    plist.Name = "esci";             //添加节点Name并赋值为esci
}

plist.Save(file);                        //保存为plist文件

2.解析json

    public class Json : DynamicObject
    {
        private IDictionary<string, object> Dictionary;

        public Json(IDictionary<string, object> dictionary)
        {
            this.Dictionary = dictionary;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = this.Dictionary[binder.Name];

            if (result is IDictionary<string, object>)
            {
                this.Dictionary[binder.Name] = result = new Json(result as IDictionary<string, object>);
            }
            else if (result is IEnumerable && !(result is string))
            {
                var list = new List<object>();
                foreach (var i in (result as IEnumerable))
                {
                    if (i is IDictionary<string, object>)
                        list.Add(new Json(i as IDictionary<string, object>));
                    else
                        list.Add(i);
                }
               this.Dictionary[binder.Name] = result = list;
            }

            return true;
        }

        static readonly JavaScriptSerializer jss = new JavaScriptSerializer();

        public static dynamic Deserialize(string json)
        {
            return new Json(jss.Deserialize(json, typeof(object)) as IDictionary<string, object>);
        }

        public static string Serialize(object obj) 
        {
            return jss.Serialize(obj);
        }
    }

  使用方法:

dynamic json = Json.Deserialize(str);
if (json != null)
{
    string msg = json.message;
    ......
}

  

posted @ 2013-04-19 16:55  RayTracer  阅读(842)  评论(0编辑  收藏  举报