質問

I want to implement serialization from CLR objects into a JSON string, but I have the following constraints:

  1. I cannot use an external library. My project is a library itself and I cannot introduce a dependency.
  2. Serialization must be one way. i.e. my .Net objects will not have any setters. This is because it will be impossible to serialize some of the data from JSON back to managed objects.
  3. It must be dynamic. Some of the types to be serialized will not be known until runtime.
  4. It must be fast, for obvious reasons. I have considered using reflection and doing the serialization manually, but I am afraid of the time penalty.
役に立ちましたか?

解決

Your question seems to be extremely broad and inviting people to provide you a ready-to-go solution. I am not going to do that, but I can give you hints on addressing issues with 3 vs 4

Here is some base code to read an object of arbitrary type into a collection of key-value pairs:

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

This allows you to create a reader delegate, that is as quick and efficient as any statically compiled code. That should give you enough direction to take it to whatever you want to do with it.

The next steps would be creating all the plumbing:

  1. Recursively walk the object tree you are trying to serialize
  2. Create and/or cache readers
  3. Read key-value pairs and write them into JSON.

These are all trivial tasks that you should be taking care of yourself. JSON spec is publicly available at http://json.org/

Good luck.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top