tis*_*hma 9 wcf serialization json datacontractserializer
我打算构建一个WCF服务,返回序列化为JSON的通用字典对象.不幸的是,序列化失败,因为对象可能总是不同.KnownTypes无法帮助,因为属性类型是Dictionary,我不能说KnownType,因为类可能总是不同.
如果有可能序列化"未知类型"的任何想法?
我不介意为每个类指定DataContract/DataMember,但(至少对于原型版本)我不希望每个响应都有强类型.Javascript客户端只是不在乎.
匿名课怎么样?
注意:我在答案开始时已经了解了很多关于JavaScriptSerializer的细节,如果您只想阅读原始问题中提到的已知类型问题的解决方案,请跳到答案的末尾.
性能
基于我运行的基准测试,JavaScriptSerializer比其他替代方案慢得多,并且与DataContractSerializer相比,可以花费2倍的时间来序列化/反序列化对象.
不需要已知类型
也就是说,JavascriptSerializer更灵活,因为它不需要您提前指定"已知类型",并且序列化的JSON至少在字典的情况下更清晰(参见此处的示例).
围绕已知类型的灵活性的另一面是它无法将相同的JSON字符串反序列化回原始类型.例如,假设我有一个简单的Person类:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我在序列化之前创建了一个实例Dictinoary<string, object>并添加了Person该类的实例:
var dictionary = new Dictionary<string, object>();
dictionary.Add("me", new Person { Name = "Yan", Age = 30 });
var serializer = new new JavaScriptSerializer();
var json = serializer .Serialize(dictionary);
Run Code Online (Sandbox Code Playgroud)
我将获得以下JSON {"me":{"Name":"Yan","Age":30}},它非常干净,但没有任何类型信息.所以假设你有两个具有相同成员定义的类,或者如果Person是子类而不引入任何其他成员:
public class Employee : Person
{
}
Run Code Online (Sandbox Code Playgroud)
那么序列化器根本无法保证JSON {"Name":"Yan","Age":30}可以反序列化为正确的类型.
如果{"me":{"Name":"Yan","Age":30}}使用JavaScriptSerializer进行反序列化,则在字典中返回与"me"相关联的值不是一个实例,Person而是Dictionary<string, object>一个简单的属性包.
如果你想获得一个Person实例,你可以(虽然你很可能永远不会想!)Dictionary<string, object>使用ConvertToTypehelper方法转换它:
var clone = serializer.Deserialize<Dictionary<string, object>>(json);
var personClone = serializer.ConverToType<Person>(clone["me"]);
Run Code Online (Sandbox Code Playgroud)
在另一方面,如果你并不需要担心反序列化JSON那些为正确的类型和JSON serailization不是一个性能瓶颈(分析代码并找出多少CPU时间的花费上的序列化,如果你还没有这样做已经)然后我会说只使用JavaScriptSerializer.
注入已知类型
如果,在一天结束时,你仍然需要使用DataContractSerializer并需要注入那些KnownTypes,这里有两件事你可以试试.
1)将已知类型的数组传递给DataContractSerializer 构造函数.
2)将DataContractResolver的子类(带有定位您感兴趣的类型的方法)传递给DataContractSerializer 构造函数
您可以创建各种各样的"已知类型的注册表",用于跟踪,可被添加到字典的类型,如果你控制,你需要注入到DataContractSerializer的所有类型,你可以尝试简单的事情:
KnownTypeRegister使用静态方法创建一个类,以将类型添加到已知类型列表中:
public static class KnownTypeRegister
{
private static readonly ConcurrentBag _knownTypes = new ConcurrentBag();
public static void Add(Type type)
{
_knownTypes.Add(type);
}
public static IEnumerable Get()
{
return _knownTypes.ToArray();
}
}添加一个静态构造函数,用寄存器注册类型:
[DataContract]
public class Person
{
static Person()
{
KnownTypeRegister.Add(typeof(Person));
}
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
}在构造序列化程序时从寄存器中获取已知类型的数组:
var serializer = new DataContractSerializer(typeof(Dictionary<string, object>), KnownTypeRegister.Get());
更多动态/更好的选择是可能的,但他们也更难以实现,如果你想了解更多有关动态已知类型解析,看看在话题朱瓦尔·洛的MSDN文章在这里.此外,Carlos Figueira撰写的这篇博文还详细介绍了更多先进的技术,例如动态生成类型,非常值得您阅读的主题!
| 归档时间: |
|
| 查看次数: |
8828 次 |
| 最近记录: |