我正在尝试反序列化包含许多基于接口的集合的json字符串。我已经实现了一个IContractResolver并使用IoC容器(TinyIoC)将接口解析为具体类 - 我遇到的麻烦是嵌套集合似乎没有填充具有实际值的具体类。
以下是一个示例。
namespace JsonIssue
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
internal class Program
{
private static void Main(string[] args)
{
var container = new TinyIoC.TinyIoCContainer();
container.Register<ISampleInterface1, SampleClass1>();
container.Register<ISampleInterface2, SampleClass2>();
container.Register<ISampleInterface3, SampleClass3>();
var obj1 = new SampleClass1();
for (int i = 0; i < 10; i++)
{
obj1.Items.Add(new SampleClass2 { Name = string.Format("Item {0}", i), Items = new List<ISampleInterface3> { new SampleClass3 { Name = "shawn 1"}} });
}
var js = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new SampleContractResolver(container)
};
var s = JsonConvert.SerializeObject(obj1);
var r = JsonConvert.DeserializeObject<SampleClass1>(s, js);
Debug.WriteLine(r);
}
}
public interface ISampleInterface1
{
string Name { get; set; }
ICollection<ISampleInterface2> Items { get; set; }
}
public interface ISampleInterface2
{
string Name { get; set; }
ICollection<ISampleInterface3> Items { get; set; }
}
public interface ISampleInterface3
{
string Name { get; set; }
}
public class SampleClass1 : ISampleInterface1
{
public SampleClass1()
{
Items = new List<ISampleInterface2>();
}
public string Name { get; set; }
public ICollection<ISampleInterface2> Items { get; set; }
}
public class SampleClass2 : ISampleInterface2
{
public SampleClass2()
{
Items = new List<ISampleInterface3>();
}
public string Name { get; set; }
public ICollection<ISampleInterface3> Items { get; set; }
}
public class SampleClass3 : ISampleInterface3
{
public string Name { get; set; }
}
public class SampleContractResolver : DefaultContractResolver
{
private readonly TinyIoC.TinyIoCContainer _container;
public SampleContractResolver(TinyIoC.TinyIoCContainer container)
{
_container = container;
}
public override JsonContract ResolveContract(Type type)
{
var contract = base.CreateObjectContract(type);
if (this._container.CanResolve(type))
{
contract.DefaultCreator = () => this._container.Resolve(type);
}
return contract;
}
}
}