C# 当从接口序列化泛型类时,如何让DataContractJsonSerializer在类型提示中使用具体类型
我有一组如下的类:一个命令,它执行并存储一个结果; 一个响应,创建为以序列化形式返回结果(加上我遗漏的额外元数据)。Response.Result必须是object类型,因为它用于一系列不同的命令,每个命令都可以有任何类型的结果 该命令是泛型的,我希望它接受接口而不是具体类型,但当我接受时,序列化响应包含以下类型提示:“\uu类型”:“ResultOfanyType:\u35;序列化” "__type":"ResultOfanyType:#serialization" 而不是在命令接受具体类型时生成的以下内容: "__type":"ResultOfMyObjectDhOQ6IBI:#serialization" “类型”:“ResultOfMyObject DHOq6IBI:#序列化” 我需要类型提示来包含具体类型,而不是ResultOfanyType。为什么在此上下文中对接口的处理不同?请注意,如果类型是序列化命令的直接属性,则具体类型包含在类型提示中 我尝试将结果的响应属性类型更改为Result,但没有效果 这是代码。只需取消注释/注释Main中创建命令的行,以及为替代版本列出的已知类型C# 当从接口序列化泛型类时,如何让DataContractJsonSerializer在类型提示中使用具体类型,c#,generics,serialization,interface,datacontractjsonserializer,C#,Generics,Serialization,Interface,Datacontractjsonserializer,我有一组如下的类:一个命令,它执行并存储一个结果; 一个响应,创建为以序列化形式返回结果(加上我遗漏的额外元数据)。Response.Result必须是object类型,因为它用于一系列不同的命令,每个命令都可以有任何类型的结果 该命令是泛型的,我希望它接受接口而不是具体类型,但当我接受时,序列化响应包含以下类型提示:“\uu类型”:“ResultOfanyType:\u35;序列化” "__type":"ResultOfanyType:#serialization" 而不是在命令接受具体类型时
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace serialization
{
class Program
{
static void Main(string[] args)
{
Response response = new Response();
response.ResponseStatus = "ok";
ConcreteCommand command = new ConcreteCommand(); //switch with line below to test inteface
//InterfaceCommand command = new InterfaceCommand();
command.Execute();
response.Results = command.Results;
List<Type> knownTypes = new List<Type>
{
typeof(Result<MyObject>), //switch with Interface lines below to test inteface
typeof(MyObject)
//typeof(Result<IMyObject>),
//typeof(IMyObject)
};
DataContractJsonSerializer serializer = new DataContractJsonSerializer(response.GetType(), knownTypes, int.MaxValue, false, null, true);
Stream stream = new MemoryStream();
serializer.WriteObject(stream, response);
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
string output = reader.ReadToEnd();
Console.WriteLine(output);
}
}
public interface IMyObject
{
string name { get; set; }
}
[DataContract]
[KnownType(typeof(MyObject))]
public class MyObject : IMyObject
{
[DataMember]
public string name { get; set; }
}
[DataContract]
public class Result<T>
{
[DataMember]
public string Status { get; set; }
[DataMember]
public T Item { get; set; }
}
public abstract class BaseCommand<T>
{
protected Result<T> results = new Result<T>();
protected T resultObject;
public object Results
{
get { return this.results; }
}
public T ResultObject
{
get { return this.resultObject; }
}
public abstract void Execute();
}
public class InterfaceCommand : BaseCommand<IMyObject>
{
public override void Execute()
{
IMyObject myobject = new MyObject();
myobject.name = "my object";
Result<IMyObject> result = new Result<IMyObject>();
result.Item = myobject;
result.Status = "ok";
this.results= result;
this.resultObject = myobject;
}
}
public class ConcreteCommand : BaseCommand<MyObject>
{
public override void Execute()
{
MyObject myobject = new MyObject();
myobject.name = "my object";
Result<MyObject> result = new Result<MyObject>();
result.Item = myobject;
result.Status = "ok";
this.results = result;
this.resultObject = myobject;
}
}
[DataContract]
public class Response
{
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
public object Results { get; set; }
}
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Runtime.Serialization;
使用System.Runtime.Serialization.Json;
命名空间序列化
{
班级计划
{
静态void Main(字符串[]参数)
{
响应=新响应();
response.ResponseStatus=“确定”;
ConcreteCommand=new ConcreteCommand();//使用下面的行切换以测试接口
//InterfaceCommand命令=新的InterfaceCommand();
command.Execute();
response.Results=command.Results;
List knownTypes=新列表
{
typeof(Result),//使用下面的接口行切换以测试接口
类型(MyObject)
//类型(结果),
//类型(IMyObject)
};
DataContractJsonSerializer=新的DataContractJsonSerializer(response.GetType(),knownTypes,int.MaxValue,false,null,true);
Stream=新的MemoryStream();
serializer.WriteObject(流、响应);
流位置=0;
StreamReader=新的StreamReader(流);
字符串输出=reader.ReadToEnd();
控制台写入线(输出);
}
}
公共接口IMyObject
{
字符串名称{get;set;}
}
[数据合同]
[知识类型(类型(MyObject))]
公共类MyObject:IMyObject
{
[数据成员]
公共字符串名称{get;set;}
}
[数据合同]
公开课成绩
{
[数据成员]
公共字符串状态{get;set;}
[数据成员]
公共T项{get;set;}
}
公共抽象类BaseCommand
{
受保护的结果=新结果();
受保护的结果对象;
公共对象结果
{
获取{返回this.results;}
}
公共结果对象
{
获取{返回this.resultObject;}
}
公共抽象void Execute();
}
公共类接口命令:BaseCommand
{
公共覆盖无效执行()
{
IMyObject myobject=新的myobject();
myobject.name=“我的对象”;
结果=新结果();
结果:项目=myobject;
result.Status=“ok”;
结果=结果;
this.resultObject=myobject;
}
}
公共类命令:BaseCommand
{
公共覆盖无效执行()
{
MyObject MyObject=新的MyObject();
myobject.name=“我的对象”;
结果=新结果();
结果:项目=myobject;
result.Status=“ok”;
这个结果=结果;
this.resultObject=myobject;
}
}
[数据合同]
公众课堂反应
{
[数据成员]
公共字符串ResponseStatus{get;set;}
[数据成员]
公共对象结果{get;set;}
}
}
让我们从这个问题开始,这可能会解释一切
我需要类型提示来包含具体类型,而不是ResultOfanyType。为什么在此上下文中对接口的处理不同
接口基本上只是实现它的类应该包含什么的契约,多个类可以实现它的成员。比如说
public interface IPerson
{
int Id { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
}
public class Person : IPerson
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Contact : IPerson
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
public string PhoneNumber { get; set; }
}
那么,当你打电话给IPerson
时,你期望得到什么?人
或联系人
?每个都有一个id和一个名称的基本组成部分,但每个都有IPerson
甚至不知道存在的唯一属性。这就是为什么当您试图获得一个接口来解析为一个具体的类时,如果没有某种工厂类来确定您想要什么,那么您将一事无成。所以在本例中,如果我想解析一个IPerson
,我会添加以下代码行
var objectType = iPersonObject.GetType();
在您的情况下,您应该尝试调用result.Item
上的GetType()
。这会告诉.NET查看实现接口的对象的实际类型并返回它。这个如何
class Program
{
static void Main(string[] args)
{
Response response = new Response();
response.ResponseStatus = "ok";
//ConcreteCommand command = new ConcreteCommand(); //switch with line below to test inteface
InterfaceCommand command = new InterfaceCommand();
command.Execute();
response.Results = command.Results;
List<Type> knownTypes = new List<Type>
{
typeof(MyObject),
typeof(Result<MyObject>) //switch with line below to test inteface
//typeof(Result<IMyObject>)
};
DataContractJsonSerializer serializer = new DataContractJsonSerializer(response.GetType(), knownTypes, int.MaxValue, false, null, true);
Stream stream = new MemoryStream();
serializer.WriteObject(stream, response);
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
string output = reader.ReadToEnd();
Console.WriteLine(output);
}
}
public interface IMyObject
{
string name { get; set; }
}
[DataContract]
public class MyObject : IMyObject
{
[DataMember]
public string name { get; set; }
}
[DataContract]
public class Result<T>
{
[DataMember]
public string Status { get; set; }
[DataMember]
public T Item { get; set; }
}
public abstract class BaseCommand
{
protected Result<IMyObject> results = new Result<IMyObject>();
public Result<IMyObject> Results
{
get { return this.results; }
}
public abstract void Execute();
}
public class InterfaceCommand : BaseCommand
{
public override void Execute()
{
IMyObject myobject = new MyObject();
myobject.name = "my object";
Result<IMyObject> result = new Result<IMyObject>();
result.Item = myobject;
result.Status = "ok";
this.results= result;
}
}
public class ConcreteCommand : BaseCommand
{
public override void Execute()
{
MyObject myobject = new MyObject();
myobject.name = "my object";
Result<IMyObject> result = new Result<IMyObject>();
result.Item = myobject;
result.Status = "ok";
this.results = result;
}
}
[DataContract]
public class Response
{
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
public Result<IMyObject> Results { get; set; }
}
如果您试图建立某种类型的通用契约,那么必须有某种类型的公共基类/接口。它不适用于对象,但您可以使用ala COM创建自己的IUnknown接口,从中创建任意多的子类,只要它们包含在已知类型中 KnownType属性可用于将接口与类的类型关联。我
{"__type":"Response:#ConsoleApplication2","ResponseStatus":"ok","Results":{"__ty
pe":"ResultOfanyType:#ConsoleApplication2","Item":{"__type":"MyObject:#ConsoleAp
plication2","name":"my object"},"Status":"ok"}}