对于WCF,何时需要静态告诉序列化程序有关数据类型的信息?

时间:2010-01-08 16:03:40

标签: c# asp.net-mvc wcf json serialization

我正在使用WCF JSON序列化程序生成JSON,以用作ASP.NET MVC框架的返回数据。我这样做是因为内置的JsonAction没有提供任何方法来控制序列化JSON中公共属性的命名。

public override void ExecuteResult(ControllerContext context)
{
    ...

    if (Data != null)
    {
        var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(Data.GetType());
        System.IO.MemoryStream ms = new System.IO.MemoryStream();

        serializer.WriteObject(ms, this.Data);

        response.Write(Encoding.Default.GetString(ms.ToArray()));
    }
}

在这个例子中,我在OpenFlashChart中使用它,所以我将this.Data设置为PieChart实例。它工作正常。然后,我将this.Data设置为Chart的实例,我得到以下异常:

Type 'OpenFlashChart.Pie' with data contract name 'Pie:http://schemas.datacontract.org/2004/07/OpenFlashChart' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

显然,当我给序列化程序一个PieChart元素时,它能够推断出我也需要Pie类。为什么我提供它Chart<PieChart>时,是否不再查看PieChart使用的类?有没有办法解决这个问题,而无需用KnownTypeAttributes注释所有内容?

2 个答案:

答案 0 :(得分:1)

我编辑了之前的答案,因为我刚刚意识到这个问题。

我认为问题是因为被序列化的类型是通用的,你必须将任何通用参数类型添加到DataContractJsonSerializer的已知类型。

如果我是对的,那么你仍然可以在没有注释的情况下这样做。

首先,在DataContractJsonSerializer上调用构造函数,该构造函数接受TypeIEnumerable<Type>

然后将构建序列化器的方式更改为:

DataContractJsonSerializer serializer = null;
Type dataType = Data.GetType();
if(dataType.IsGenericType)
    serializer = new DataContractJsonSerializer(dataType, dataType.GetGenericArguments());
else
    serializer = new DataContractJsonSerializer(dataType);

这将是我的下一步。

答案 1 :(得分:0)

由于Andras的帖子最初是我在JSON序列化/反序列化方面实现的解决方案之一,并且自那以后发现了一种更好的方法(至少为我自己的目的),我想分享一下:

// Add a reference to System.Web.Extensions **(.NET 4.0 required)**

using System.Web.Script.Serialization;
...
// To serialize...
JavaScriptSerializer serializer = new JavaScriptSerializer();
String serializedData = serializer.Serialize(data);

// To deserialize...
deserializedData = serializer.Deserialize<data.GetType()>(serializedData);
// OR even
var anyObject = .serializer.Deserialize<dynamic>(serializedData);

很简单