动态类型序列化

上一篇文章直接就被移除首页了,这次来点大家都能懂的干货.

需求

之前做一个winform的工具时候有以下几个需求
1. 主窗体(或者叫平台)可以安装若干类型的插件。
2. 插件关闭时候需要保存状态。
3. 插件加载的时候可以加载上次关闭的配置。
4. 插件中的配置可以切换。
5. 主窗体本身保存当前插件,并且可以通过不同的配置文件切换插件

使用上最方便的做法是将配置给平台来管理。但是平台本身并不知道插件要保存怎样的配置。针对以上问题在配置这个上做了如下设计

设计

1. 动态类型序列化以满足插件的任何配置需要
2. 动态类型基本的就是dynamic,那么我们需用字典作为实现
3. 支持具体的类进行序列化,那么此时需要用xml保存类的元数据信息
4. 支持接口的序列化,此时也是保存实际类型的元数据信息
5. 支持List序列化
6. 支持Arry序列化
7. 支持Dictionary序列化

接口定义

其中PathOrSourceString 属性这样既可以支持文件,也可以直接支持字符串,扩展更加方便.

public interface IConfig
    {
        string PathOrSourceString { get; set; }

        dynamic Data { get; set; }
    }

动态类型实现

这里是基于字典,网上有很多类似的代码。

这里字典的Value设计成dynamic是为了嵌套。

    [Serializable]
    public class DynamicDictionary : DynamicObject
    {
        private Dictionary<string, dynamic> _dictionary = new Dictionary<string, dynamic>();

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            string name = binder.Name;
            if (!_dictionary.ContainsKey(name))
            {
                _dictionary.Add(name, new DynamicDictionary());
            }
            return _dictionary.TryGetValue(name, out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            var key = binder.Name;
            if (_dictionary.ContainsKey(key))
                _dictionary[key] = value;
            else
            {
                _dictionary.Add(key, value);
            }

            return true;
        }

        public Dictionary<string, dynamic> Dictionary
        {
            get { return _dictionary; }
        }

        public void AddMember(string name, dynamic value)
        {
            _dictionary.Add(name, value);
        }
    }

  

配置的加载和保存逻辑(核心)

    public static class ConfigManager
    {
        public static IConfig LoadFromFile(this IConfig config)
        {
            if (config == null || string.IsNullOrEmpty(config.PathOrSourceString))
                throw new ArgumentNullException("config");
            if (!File.Exists(config.PathOrSourceString))
            {
                return config;
            }
            var doc = new XmlDocument();
            doc.Load(config.PathOrSourceString);
            var element = doc["Data"];
            config.Data = GetValue(element);
            return config;
        }

        public static IConfig SaveToFile(this IConfig config)
        {
            if (config == null || string.IsNullOrEmpty(config.PathOrSourceString) || config.Data == null)
                throw new ArgumentNullException("config");
            var dir = Path.GetDirectoryName(config.PathOrSourceString);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            var doc = new XmlDocument();
            doc.AppendChild(GetXml("Data", config.Data, doc));
            doc.Save(config.PathOrSourceString);
            return config;
        }

        public static IConfig LoadFromString(this IConfig config)
        {
            if (config == null || string.IsNullOrEmpty(config.PathOrSourceString))
                throw new ArgumentNullException("config");
            var doc = new XmlDocument();
            doc.LoadXml(config.PathOrSourceString);
            var element = doc["Data"];
            config.Data = GetValue(element);
            return config;
        }

        public static IConfig SaveToString(this IConfig config)
        {
            if (config == null || config.Data == null)
                throw new ArgumentNullException("config");
            var doc = new XmlDocument();
            doc.AppendChild(GetXml("Data", config.Data, doc));
            config.PathOrSourceString = doc.OuterXml;
            return config;
        }

        #region 解析XmlElement

        public static dynamic GetValue(XmlElement element)
        {
            if (element == null)
                return null;

            Classify clasify;
            Enum.TryParse(element.GetAttribute("Classify"), out clasify);
            switch (clasify)
            {
                case Classify.Sample:
                    return GetSampleValue(element.GetAttribute("Assembly"), element.GetAttribute("Type"), element.InnerText);
                case Classify.Array:
                    return GetArrayValue(element.GetAttribute("ElementAssembly"), element.GetAttribute("ElementType"), element.GetChidlren());
                case Classify.List:
                    return GetListValue(element.GetAttribute("GenericAssembly"), element.GetAttribute("GenericType"), element.GetChidlren());
                case Classify.Dictionary:
                    return GetDictionaryValue(element.GetAttribute("KeyGenericAssembly"),
                        element.GetAttribute("KeyGenericType"),
                        element.GetAttribute("ValueGenericAssembly"),
                        element.GetAttribute("ValueGenericType"),
                        element.GetChidlren());
                case Classify.Dynamic:
                    return GetDynamicValue(element.GetChidlren());
                case Classify.Custom:
                    return GetCustomValue(element.GetAttribute("Assembly"), element.GetAttribute("Type"), element.GetChidlren());
            }

            return null;
        }
        public static object GetSampleValue(string assembly, string typeFullName, string value)
        {
            var type = Assembly.Load(assembly).GetType(typeFullName);
            if (type == null)
                return null;
            return CoralConvert.Convert(value, type);
        }
        public static object GetListValue(string genericAssembly, string genericTypeName, List<XmlElement> elements)
        {
            var genericType = Assembly.Load(genericAssembly).GetType(genericTypeName);
            var type = typeof(List<>).MakeGenericType(genericType);
            dynamic list = Activator.CreateInstance(type, true);

            foreach (var element in elements)
            {
                list.Add(GetValue(element));
            }
            return list;
        }
        public static object GetArrayValue(string elementAssembly, string elementTypeName, List<XmlElement> elements)
        {
            var elementType = Assembly.Load(elementAssembly).GetType(elementTypeName);
            dynamic list = Array.CreateInstance(elementType, elements.Count);
            for (int i = 0; i < elements.Count; i++)
            {
                list[i] = GetValue(elements[i]);
            }
            return list;
        }
        public static object GetDictionaryValue(string keyAssembly, string keyTypeName, string valueAssembly, string valueTypeName, List<XmlElement> elements)
        {
            var keyType = Assembly.Load(keyAssembly).GetType(keyTypeName);
            var valueType = Assembly.Load(valueAssembly).GetType(valueTypeName);
            var type = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
            dynamic dict = Activator.CreateInstance(type, true);
            foreach (var element in elements)
            {
                dict.Add(GetValue(element["Key"]), GetValue(element["Value"]));
            }
            return dict;
        }
        public static object GetDynamicValue(List<XmlElement> elements)
        {
            var dict = new DynamicDictionary();
            foreach (var element in elements)
            {
                dict.Dictionary.Add(GetValue(element["Key"]), GetValue(element["Value"]));
            }
            return dict;
        }
        public static object GetCustomValue(string assemblyFullName, string typeFullName, List<XmlElement> elements)
        {
            var type = Assembly.Load(assemblyFullName).GetType(typeFullName);
            if (type == null)
                return null;
            dynamic obj = Activator.CreateInstance(type, true);

            foreach (var element in elements)
            {
                var property = type.GetProperty(element.Name);
                object value;
                if (!CoralConvert.Convert(GetValue(element), property.PropertyType, out value))
                    continue;
                property.SetValue(obj, value);
            }

            return obj;
        }
        #endregion

        #region 创建XmlElement

        /// <summary>
        /// 创建xml元素
        /// </summary>
        /// <param name="name"></param>
        /// <param name="data"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public static XmlElement GetXml(string name, object data, XmlDocument doc)
        {
            if (data == null)
                return null;
            if (data.GetType().IsValueType || data is string)
            {
                return GetValueTypeXml(name, data, doc);
            }
            var list = data as IList;
            if (list != null)
            {
                return GetIListXml(name, list, doc);
            }
            var dict = data as IDictionary;
            if (dict != null)
            {
                return GetIDictionaryXml(name, dict, doc);
            }
            var dynamic = data as DynamicDictionary;
            if (dynamic != null)
            {
                return GetDynamicXml(name, dynamic, doc);
            }
            return GetCustomXml(name, data, doc);
        }

        /// <summary>
        /// 创建简单类型的xml元素
        /// </summary>
        /// <param name="name"></param>
        /// <param name="data"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetValueTypeXml(string name, object data, XmlDocument doc)
        {
            if (data == null)
                return null;
            var element = doc.CreateElement(name);
            element.SetAttribute("Type", data.GetType().FullName);
            element.SetAttribute("Assembly", MetaDataManager.Assembly.GetAssemblySortName(data.GetType().Assembly));
            element.SetAttribute("Classify", Classify.Sample.ToString());
            element.InnerText = data.ToString();
            return element;
        }

        /// <summary>
        /// 获取列表类型的xml
        /// </summary>
        /// <param name="name"></param>
        /// <param name="datas"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetIListXml(string name, object datas, XmlDocument doc)
        {
            if (datas == null)
                return null;
            var element = doc.CreateElement(name);
            if (datas.GetType().IsArray)
            {
                element.SetAttribute("Type", typeof(Array).FullName);
                element.SetAttribute("Classify", Classify.Array.ToString());
                element.SetAttribute("ElementType", datas.GetType().GetElementType().FullName);
                element.SetAttribute("ElementAssembly", datas.GetType().GetElementType().Assembly.FullName);
            }
            else
            {
                element.SetAttribute("Type", typeof(IList).FullName);
                element.SetAttribute("Classify", Classify.List.ToString());
                element.SetAttribute("GenericType", datas.GetType().GenericTypeArguments[0].FullName);
                element.SetAttribute("GenericAssembly", datas.GetType().GenericTypeArguments[0].Assembly.FullName);
            }
            foreach (var data in (IList)datas)
            {
                element.AppendChild(GetXml("Element", data, doc));
            }
            return element;
        }

        /// <summary>
        /// 创建动态类型的xml
        /// </summary>
        /// <param name="name"></param>
        /// <param name="data"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetDynamicXml(string name, dynamic data, XmlDocument doc)
        {
            if (data == null)
                return null;
            var element = doc.CreateElement(name);
            element.SetAttribute("Type", "dynamic");
            element.SetAttribute("Classify", Classify.Dynamic.ToString());
            foreach (DictionaryEntry item in (IDictionary)data.Dictionary)
            {
                var child = doc.CreateElement("Element");
                child.AppendChild(GetXml("Key", item.Key ?? string.Empty, doc));
                child.AppendChild(GetXml("Value", item.Value ?? string.Empty, doc));
                element.AppendChild(child);
            }
            return element;
        }

        /// <summary>
        /// 创建字典类型的xml
        /// </summary>
        /// <param name="name"></param>
        /// <param name="datas"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetIDictionaryXml(string name, object datas, XmlDocument doc)
        {
            if (datas == null)
                return null;
            var element = doc.CreateElement(name);
            element.SetAttribute("Type", typeof(IDictionary).FullName);
            element.SetAttribute("Classify", Classify.Dictionary.ToString());
            element.SetAttribute("KeyGenericAssembly", datas.GetType().GetGenericArguments()[0].Assembly.FullName);
            element.SetAttribute("KeyGenericType", datas.GetType().GetGenericArguments()[0].FullName);
            element.SetAttribute("ValueGenericAssembly", datas.GetType().GetGenericArguments()[1].Assembly.FullName);
            element.SetAttribute("ValueGenericType", datas.GetType().GetGenericArguments()[1].FullName);
            foreach (DictionaryEntry data in (IDictionary)datas)
            {
                var child = doc.CreateElement("Element");
                child.AppendChild(GetXml("Key", data.Key ?? string.Empty, doc));
                child.AppendChild(GetXml("Value", data.Value ?? string.Empty, doc));
                element.AppendChild(child);
            }
            return element;
        }

        /// <summary>
        /// 创建自定义类
        /// </summary>
        /// <param name="name"></param>
        /// <param name="data"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetCustomXml(string name, object data, XmlDocument doc)
        {
            if (data == null)
                return null;
            var element = doc.CreateElement(name);
            element.SetAttribute("Assembly",MetaDataManager.Assembly.GetAssemblySortName(data.GetType().Assembly));
            element.SetAttribute("Type", data.GetType().FullName);
            element.SetAttribute("Classify", Classify.Custom.ToString());
            data.GetType().GetProperties().ForEach(property =>
            {
                var item = GetXml(property.Name, property.GetValue(data), doc);
                if (item != null)
                    element.AppendChild(item);
            });
            return element;
        }

        #endregion

        public enum Classify
        {
            Sample,
            List,
            Array,
            Dictionary,
            Dynamic,
            Custom,
        }
        public static List<XmlElement> GetChidlren(this XmlElement element)
        {
            return element.Cast<XmlElement>().ToList();
        }
    }

  

  

核心思路就是递归,充分利用元数据

测试代码

 public class XmlConfig : IConfig
    {
        public string PathOrSourceString { get; set; }
        public dynamic Data { get; set; }
    }

    public interface ITestModel
    {

        string Name { get; set; }

        string DataType { get; set; }

        string Data { get; set; }

    }

    public class TestConfig
    {
        public ITestModel Model { get; set; }

        public  List<ITestModel> List { get; set; }
        public Dictionary<string, ITestModel> Dict { get; set; }
    }

    public class TestModel: ITestModel
    {
        public string Name { get; set; }

        public string DataType { get; set; }

        public string Data { get; set; }

        public List<ITestModel> List { get; set; }
        public Dictionary<string, ITestModel> Dict { get; set; }
    }

    public class ConfigTest
    {
        public static void PerformanceTest()
        {
            var xmlconfig = new XmlConfig();

            xmlconfig.PathOrSourceString = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs", "test1.Config");

            #region list 类,字典测试

            var testModel=   new TestModel()
            {
                Name = "1",
                DataType = "1",
                Data = "1",
                List = new List<ITestModel>
                {
                    new TestModel
                    {
                        Name = "2",
                        DataType = "2",
                        Data = "2",
                    },
                    new TestModel
                    {
                        Name = "3",
                        DataType = "3",
                        Data = "3",
                    },
                },
                Dict = new Dictionary<string, ITestModel>
                {
                    {"4", new TestModel
                            {
                                Name = "4",
                                DataType = "4",
                                Data = "4",
                            }
                     },
                    {"5", new TestModel
                            {
                                Name = "5",
                                DataType = "5",
                                Data = "5",
                            }
                     },
                }
            };
            #endregion

            xmlconfig.Data = new TestConfig()
            {
                Model = testModel,
                Dict = new Dictionary<string, ITestModel>()
                {
                    {"1",testModel },
                    {"2",testModel }
                },
                List = new List<ITestModel> { testModel,testModel}
            };

            #region 动态类型,类,list,字典总和测试

            xmlconfig.Data = new DynamicDictionary();

            xmlconfig.Data.Name = "Test1";
            xmlconfig.Data.DataType = "Test1";

            xmlconfig.Data.List = new List<TestModel>
            {
                new TestModel
                {
                    Name = "2",
                    DataType = "2",
                    Data = "2",
                },
                new TestModel
                {
                    Name = "3",
                    DataType = "3",
                    Data = "3",
                },
            };
            xmlconfig.Data.Dict = new Dictionary<string, TestModel>
            {
                {
                    "4", new TestModel
                    {
                        Name = "4",
                        DataType = "4",
                        Data = "4",
                    }
                },
                {
                    "5", new TestModel
                    {
                        Name = "5",
                        DataType = "5",
                        Data = "5",
                    }
                },
            };
            xmlconfig.Data.Other.Name = "Test1";
            xmlconfig.Data.Other.DataType = "Test1";

            #endregion

            xmlconfig.SaveToFile();

            var data = new XmlConfig();

            data.PathOrSourceString = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs", "test1.Config");
            data.LoadFromFile();
        }

 配置文件为

<Data Type="dynamic" Classify="Dynamic">
  <Element>
    <Key Type="System.String" Assembly="mscorlib" Classify="Sample">Name</Key>
    <Value Type="System.String" Assembly="mscorlib" Classify="Sample">Test1</Value>
  </Element>
  <Element>
    <Key Type="System.String" Assembly="mscorlib" Classify="Sample">DataType</Key>
    <Value Type="System.String" Assembly="mscorlib" Classify="Sample">Test1</Value>
  </Element>
  <Element>
    <Key Type="System.String" Assembly="mscorlib" Classify="Sample">List</Key>
    <Value Type="System.Collections.IList" Classify="List" GenericType="RunnerTest.Common.TestModel" GenericAssembly="RunnerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <Element Assembly="RunnerTest" Type="RunnerTest.Common.TestModel" Classify="Custom">
        <Name Type="System.String" Assembly="mscorlib" Classify="Sample">2</Name>
        <DataType Type="System.String" Assembly="mscorlib" Classify="Sample">2</DataType>
        <Data Type="System.String" Assembly="mscorlib" Classify="Sample">2</Data>
      </Element>
      <Element Assembly="RunnerTest" Type="RunnerTest.Common.TestModel" Classify="Custom">
        <Name Type="System.String" Assembly="mscorlib" Classify="Sample">3</Name>
        <DataType Type="System.String" Assembly="mscorlib" Classify="Sample">3</DataType>
        <Data Type="System.String" Assembly="mscorlib" Classify="Sample">3</Data>
      </Element>
    </Value>
  </Element>
  <Element>
    <Key Type="System.String" Assembly="mscorlib" Classify="Sample">Dict</Key>
    <Value Type="System.Collections.IDictionary" Classify="Dictionary" KeyGenericAssembly="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" KeyGenericType="System.String" ValueGenericAssembly="RunnerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ValueGenericType="RunnerTest.Common.TestModel">
      <Element>
        <Key Type="System.String" Assembly="mscorlib" Classify="Sample">4</Key>
        <Value Assembly="RunnerTest" Type="RunnerTest.Common.TestModel" Classify="Custom">
          <Name Type="System.String" Assembly="mscorlib" Classify="Sample">4</Name>
          <DataType Type="System.String" Assembly="mscorlib" Classify="Sample">4</DataType>
          <Data Type="System.String" Assembly="mscorlib" Classify="Sample">4</Data>
        </Value>
      </Element>
      <Element>
        <Key Type="System.String" Assembly="mscorlib" Classify="Sample">5</Key>
        <Value Assembly="RunnerTest" Type="RunnerTest.Common.TestModel" Classify="Custom">
          <Name Type="System.String" Assembly="mscorlib" Classify="Sample">5</Name>
          <DataType Type="System.String" Assembly="mscorlib" Classify="Sample">5</DataType>
          <Data Type="System.String" Assembly="mscorlib" Classify="Sample">5</Data>
        </Value>
      </Element>
    </Value>
  </Element>
  <Element>
    <Key Type="System.String" Assembly="mscorlib" Classify="Sample">Other</Key>
    <Value Type="dynamic" Classify="Dynamic">
      <Element>
        <Key Type="System.String" Assembly="mscorlib" Classify="Sample">Name</Key>
        <Value Type="System.String" Assembly="mscorlib" Classify="Sample">Test1</Value>
      </Element>
      <Element>
        <Key Type="System.String" Assembly="mscorlib" Classify="Sample">DataType</Key>
        <Value Type="System.String" Assembly="mscorlib" Classify="Sample">Test1</Value>
      </Element>
    </Value>
  </Element>
</Data>

  

说明

最大的用处,你拿到一个对象未知的对象,并不需要知道他的实际类型,就可以进行持久化,并且读取出来之后能够还原到原始类型。

实现这部分我觉得在于以下几个点

1. 对元数据的充分理解
2. 对xml结构的充分理解
3. 需要一点写算法的能力

我觉得代码本身并不复杂,只要耐心单步调试都能看懂。

当然这个是有一定限制的:

1. 可读性不强,所以在需要从文件进行修改配置比较麻烦

2.不可跨系统,文件中类型从程序集加载不到时就会出错

3.性能不高.性能敏感的部分不太适合

所以这部分功能需要结合业务场景使用,在我这里,包含作业调度系统,统计系统,接口测试工具中有使用.

这其实特别想WSDL的Soap协议,文件中既包含元数据的说明,又包含数据本身.真个元数据变成也是一个做设计时候一个重要思想。

时间: 2024-10-10 00:54:57

动态类型序列化的相关文章

使用动态类型dynamic让你的省了很多临时类

客户端与服务端的数据交互使用的数据格式是json格式,为了使客户端与服务端有类对应关系,进行序列化,所以总要定义一些类,使用动态类型dynamic可以不必要定义那么多类. 测试代码: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 7 namespace dynamic.Controllers 8 { 9 /

动态类型和匿名类型在asp.net webapi中的应用

1.  动态类型用于webapi调用 假设需要调用一个webapi,webapi返回了一个json字符串.字符串如下: {"ProductId":"AN002501","ProductName":"XX洗衣粉","Description":"","UnitPrice":9.9} 问:如何获得json字符串中的值? 常规的做法是:先构建一个类,然后再使用JsonConv

Python的动态类型

动态类型:                                                      在python中,类型是在运行过程中自动决定的,而不是通过代码声明的. 变量:                                                                                     变量是一个系统表的元素,拥有指向对象的连接的空间 python中,类型的概念是存在于对象中的,而不是变量中,变量是通用的. 变量的使用

OC多态,动态类型绑定

// //  main.m //  OC7类 // //  Created by Zoujie on 15/8/23. //  Copyright (c) 2015年 Zoujie. All rights reserved. // #import <Foundation/Foundation.h> #import "Fraction.h"//导入头文件 #import "Complex.h" #define Choose  0 int main(int 

.net 3.5 c#构建动态类型最佳实践

为什么要在.net3.5下面构建,有几个原因: win7自带.net 3.5 ,用户无须安装 我用的是vs2008,不想升级 .net 4.0引入了关键字,但是我想.net 3.5下面也有类似功能 这是构建orm的基础,一言以蔽之,市面上的orm都不好用,我想重新造轮子 暂时没想到 最终结果是这样的 属性名是字符串,属性值随便什么类型. 下图是我写了两个晚上的orm,多表查询生成的是动态类型List,同时映射到多个实体类,在展现层的代码量极少,便于工具生成. 我对orm的设想如下: 基础的增删改

python学习笔记17(动态类型)

动态类型 在我们接触的对象中,有一类特殊的对象,是用于存储数据的,常见的该类对象包括各种数字,字符串,表,词典.在C语言中,我们称这样一些数据结构为变量,而在Python中,这些是对象. 对象是储存在内存中的实体.但我们并不能直接接触到该对象.我们在程序中写的对象名,只是指向这一对象的引用(reference). 引用和对象分离,是动态类型的核心.引用可以随时指向一个新的对象: a = 3 a = 'python' 第一个语句中,3是储存在内存中的一个整数对象,通过赋值,引用a指向对象3. 第二

Python 动态类型

Python 动态类型 1.Python中,类型是在运行过程中自动决定的,并不需要提前在代码中声明. 2.所有变量必须在使用前明确的赋值,否则将会产生错误.#例:NameError: name 'a' is not defined 3.赋值语句 a=3 代表了:创建一个对象代表3:创建一个变量a:将变量与新的对象3相连.实际上是到对象内存空间的一个指针! 4.上面的第3条可翻译为:变量是一个系统表的元素,拥有指向对象的链接的空间:对象是分配的一块内存,有足够空间来表示他们所代表的值:引用是自动形

c++知识点总结--静态与动态类型

对象的静态类型(static type),就是它在程序中被声明时所采用的类型 对象的动态类型(dynamic type)是指“目前所指对象的类型” vitual 函数是动态绑定而来,调用一个virtual函数时,究竟调用哪一个函数实现,取决于发出调用的那个对象的动态类型 class Shape{ public: enum ShapeColor{ Red, Green, Blue = 1, Org }; void printColor(){ cout << Red << Green

Json.net实现方便的Json转C#(dynamic动态类型)对象

以前需要将一段json字符串转换为C#对象时,一般都是定义一个与之对应的实体类来接收.这样做有一个很大的缺点,就是当字符串特别长,属性特别多,又有嵌套时,手敲这个实体类就非常痛苦. 比如之前做的一个接收百度七天天气预报的API,层层嵌套,很痛苦. C# 4.0 之后有了动态类型dynamic.用这个东西配合Json.net可以实现不用定义实体类的json转dynamic类型对象. 以下示例需要先引用Newtonsoft.Json.dll public class Person { public