2013-07-07 31 views
-1

我想要实现从CLR对象序列化到JSON字符串,但我有以下限制:快速,动态的方式JSON序列化对于.NET

  1. 我不能使用外部库。我的项目本身就是一个库,我不能引入依赖关系。
  2. 序列化必须是单向的。即我的.Net对象不会有任何setter。这是因为无法将JSON中的部分数据序列化回管理对象。
  3. 它必须是动态的。一些要序列化的类型直到运行时才会知道。
  4. 由于显而易见的原因,它必须快速。我已经考虑过使用反射并手动进行序列化,但我担心时间会受到影响。
+2

你的第三和第四个要求是不可能合并的。为了动态,它必须使用反射,而且速度不能太快。 – Guffa

+0

有在ISerializable的 – Shane

回答

2

您的问题似乎非常宽泛,并邀请人们为您提供随时可用的解决方案。我不打算这样做,但我可以给你提示,在解决问题与3比4

这里是一些基本代码读取任意类型的对象为键值对的集合:

void Main() 
{ 
    var reader = CreateReader(typeof(Foo)); 
    reader(new Foo { Bar = "BARRRRR", Baz = 123 }).Dump(); 
} 

public class Foo 
{ 
    public string Bar {get; set;} 
    public int Baz {get; set;} 
} 


static ConstructorInfo Ctor = typeof(KeyValuePair<string, object>).GetConstructor(new Type[] { typeof(String), typeof(Object) }); 

static Func<object, IEnumerable<KeyValuePair<string, object>>> CreateReader(Type t) 
{ 
    var prm = Expression.Parameter(typeof(Object), "prm"); 
    var obj = Expression.Variable(t, "obj"); 
    var arr = new List<Expression>(); 

    foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
    { 
     arr.Add(Expression.New(Ctor, Expression.Constant(p.Name), Expression.Convert(Expression.Property(obj, p), typeof(Object)))); 
    } 

    var body = Expression.Block(
     typeof(IEnumerable<KeyValuePair<string, object>>), 
     new ParameterExpression[] { obj }, 
     Expression.Assign(obj, Expression.Convert(prm, t)), 
     Expression.NewArrayInit(typeof(KeyValuePair<string, object>), arr) 
    ); 

    return Expression.Lambda<Func<object, IEnumerable<KeyValuePair<string, object>>>>(body, prm).Compile(); 
} 

这允许您创建一个阅读器委托,与任何静态编译的代码一样快速高效。这应该给你足够的方向,把它带到你想做的任何事情上。

下一步将创建所有的管道:

  1. 递归走对象树你正在试图序列
  2. 创建和/或高速缓存读者
  3. 阅读键值对,并将其写入转换成JSON。

这些都是你应该照顾自己所有琐碎的任务。 JSON规范在http://json.org/

公共可用。祝你好运。

+1

反映我作为.NET消费者使用,但可以通过,比如说进行反射,DataContract序列,或者非反射分析之间的差异,这就是为什么C#是真棒!具有讽刺意味的+1 – BlackBear

+0

定义:我从来没有使用表达式树认为,尽管大部分要序列化的数据是一个表达式树:)。谢谢 – Shane