多态性 WCF 反序列化不起作用
本文关键字:不起作用 反序列化 WCF 多态性 | 更新日期: 2023-09-27 18:34:47
>我创建了以下类。 一个基类 IObject 和 2 个派生类 A 和 B。
[KnownType(typeof(B))]
[KnownType(typeof(A))]
[DataContract(Name = "IObject")]
public class IObject
{
}
[DataContract(Name="A")]
public class A : IObject
{
[DataMember]
public string s1 { get; set; } // Tag Name as it will be presented to the user
}
[DataContract(Name="B")]
public class B : IObject
{
[DataMember]
public string s2 { get; set; }
}
我还创建了以下服务:
[ServiceKnownType(typeof(B))]
[ServiceKnownType(typeof(A))]
public void GetR(IObject obj)
{
B other = (B)obj;
}
我想做的是获取 A 或 B 的实例,但我不知道我会得到哪个实例,所以我希望得到一个 IObject 并在以后将其转换为 A 或 B,如我放置的示例所示。
当我发送包含 s2 字符串的 json 字符串时发生的情况是我得到的是 IObject 实例而不是 B 实例。代码有什么问题?
我正在使用的客户端示例:
var url = serviceURL;
var data = {s2: "Data"};
var json = JSON.stringify(data);
$.ajax({
type: "POST",
url: url,
data: data,
contentType: "application/json",
dataType: 'json'
});
已编辑:我已通过以下链接将示例代码上传到gitHub:https://github.com/AlgoEitan/27588144
客户端有一个 c# 客户端(我已经用 c# 和 javascript 尝试过 - Web 浏览器客户端(
DataContractJsonSerializer
具有特定的格式,它存储有关多态类型的已知类型信息的提示,可以通过一些测试来发现这些信息。 我按原样复制并粘贴了您的类,并创建了以下测试代码:
public static class DataContractJsonSerializerPolymorphismTest
{
public static void Test()
{
var a1 = new A() { s1 = "A" };
var b1 = new B() { s2 = "B" };
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IObject));
var jsona1 = DataContractJsonSerializerHelper.GetJson(a1, serializer);
var jsonb1 = DataContractJsonSerializerHelper.GetJson(b1, serializer);
Debug.WriteLine(jsona1);
Debug.WriteLine(jsonb1);
var newa1 = DataContractJsonSerializerHelper.GetObject<IObject>(jsona1, serializer);
Debug.Assert(newa1.GetType() == a1.GetType()); // No assert
}
}
这样,就创建了以下 JSON:
{"__type":"A:#Tile.DataContractJsonSerializerPolymorphism","s1":"A"}
{"__type":"B:#Tile.DataContractJsonSerializerPolymorphism","s2":"B"}
其中Tile.DataContractJsonSerializerPolymorphism
恰好是我的测试应用程序中 CLR 命名空间的名称。 因此,如您所见,已知类型信息隐藏在这个额外的 JSON 属性__type
中。 现在,如果你也在客户端中使用DataContractJsonSerializerHelper
,你永远不会知道这一点,因为通信会起作用。 但是您正在使用没有此逻辑的JSON.stringify()
。 因此,您可能需要在客户端手动添加 "__type":"DataContractName:DataContractNamespace"
属性。
有关多态类型格式的更多信息,请参阅此处。 (我只是在找到隐藏的__type
参数后才跟踪此文档,这给了我一个额外的 Google 搜索词。
仅供参考,这是我与测试代码一起使用的帮助程序类:
public static class DataContractJsonSerializerHelper
{
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
public static string GetJson<T>(T obj, DataContractJsonSerializer serializer) where T : class
{
using (var memory = new MemoryStream())
{
serializer.WriteObject(memory, obj);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
return reader.ReadToEnd();
}
}
}
public static string GetJson<T>(T obj) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return GetJson(obj, serializer);
}
public static T GetObject<T>(string json) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return GetObject<T>(json, serializer);
}
public static T GetObject<T>(string json, DataContractJsonSerializer serializer) where T : class
{
T obj = null;
using (var stream = GenerateStreamFromString(json))
{
obj = (T)serializer.ReadObject(stream);
}
return obj;
}
}