C# DataContract序列化-我可以序列化类型属性吗?
我正在致力于提供一个通用的JSON序列化/反序列化服务作为WCF服务 为了做到这一点,我有以下数据合同C# DataContract序列化-我可以序列化类型属性吗?,c#,json,wcf,C#,Json,Wcf,我正在致力于提供一个通用的JSON序列化/反序列化服务作为WCF服务 为了做到这一点,我有以下数据合同 [DataContract] public class SerializationRequest { [DataMember] public Object Data {get;set;} //Object to be serialized [DataMember] public string Type {get;set;} //Ty
[DataContract]
public class SerializationRequest
{
[DataMember]
public Object Data {get;set;} //Object to be serialized
[DataMember]
public string Type {get;set;} //Type of the Data object
}
我遇到的问题是出现以下错误:
InnerException消息为'Type'System.RuntimeType',数据协定名称为'RuntimeType:http://schemas.datacontract.org/2004/07/System”他说。考虑使用DATACONTRORTCORDEVER或将未知类型的任何类型添加到已知类型的列表中——例如,通过使用NoNyType属性,或者将它们添加到传递给DATACONTROTTRORALIZER的已知类型列表中。有关更多详细信息,请参阅InnerException
这告诉我要么需要让DataContractJSONSerializer知道该类型,要么该类型无法序列化
我已经尝试注册对象的类型并将其添加到序列化程序“已知类型”,但这似乎不起作用,这使我相信我的问题在于在我的DataContract上有一个类型为type的参数
我怎样才能做到这一点?我需要能够调用以下代码(“ish”)
编辑
我已将类型参数更改为要序列化的类型的完整限定名,但在远程WCF服务中调用以下代码时,仍然遇到相同的问题:
Type type = Type.GetType(request.Type);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(type, new Type[]{Type.GetType(request.Type)});
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, request.Data);
string json = Encoding.Default.GetString(ms.ToArray());
ms.Dispose();
return new JSONSerializationResponse() {Data = json};
我已经尝试将创建的类型添加到DataContractJSONSerializer的构造函数中的KnownTypes中,但这也不起作用……有什么想法吗
下面是一个简单类的示例,该类将被调用,需要能够序列化
[DataContract]
[KnownType(typeof(Person))]
public class Person
{
[DataMember]
public string Age {get;set;}
[DataMember]
public strign Name {get;set;}
}
现在我应该能够通过指定类型名将其传递到我的请求对象中,然后返回该对象的JSON结果。您不能使用
类型本身,因为在运行时它将是RuntimeType
的一个实例,这是一个内部类,因此不能添加到ServiceKnownType
属性中(或者更准确地说,不能由WCF使用的DataContractSerializer
序列化)
您应该考虑将类型的程序集限定名序列化为简单字符串。这将允许您在客户端重新创建类型:
[DataContract]
public class SerializationRequest
{
// ...
[DataMember]
public string TypeName {get;set;}
}
// ...
var type = Type.GetType(response.TypeName);
var serializer = new DataContractJsonSerializer(type);
我不确定您为什么需要JSON中的.NET类型,但您可以将该类型序列化为字符串,然后显然可以从字符串创建类型
您可以使用Type.FullName和Assembly.GetType(“My.Type”)来获取字符串(序列化)并从名称创建类型(反序列化)。这样做太难了
鉴于以下情况:
[DataContract]
public class Person : BaseObject
{
[DataMember]
public string Age { get; set; }
[DataMember]
public string Name { get; set; }
}
[DataContract]
[KnownType(typeof(Person))]
public class BaseObject
{
}
static string Serialize<T>(T item)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
string result;
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, item);
result = Encoding.Default.GetString(ms.ToArray());
};
return result;
}
[DataContract]
公共类Person:BaseObject
{
[数据成员]
公共字符串年龄{get;set;}
[数据成员]
公共字符串名称{get;set;}
}
[数据合同]
[知识类型(类型(人))]
公共类基对象
{
}
静态字符串序列化(T项)
{
DataContractJsonSerializer serializer=新的DataContractJsonSerializer(typeof(T));
字符串结果;
使用(var ms=new MemoryStream())
{
serializer.WriteObject(ms,item);
结果=Encoding.Default.GetString(ms.ToArray());
};
返回结果;
}
您可以序列化一个人:
var person = new Person { Name = "Me", Age = Int16.MaxValue.ToString() };
Console.WriteLine(Serialize<Person>(person));
// Produces: {"Age":"32767","Name":"Me"}
var person=newperson{Name=“Me”,Age=Int16.MaxValue.ToString();
Console.WriteLine(序列化(person));
//产生:{“年龄”:“32767”,“姓名”:“我”}
在这种情况下,serialiser的工作原理是,可以将序列化对象反序列化为单个已知类型。无论是谁将要把这些数据拉回来,都知道会发生什么,因此类型不会被推入
或者可以序列化BaseObject:
var person = new Person { Name = "Me", Age = Int16.MaxValue.ToString() };
Console.WriteLine(Serialize<BaseObject>(person));
// Produces: {"__type":"Person:#ConsoleApplication6","Age":"32767","Name":"Me"}
var person=newperson{Name=“Me”,Age=Int16.MaxValue.ToString();
Console.WriteLine(序列化(person));
//产生:{uuuu type:“Person:#ConsoleApplication6”,“Age:“32767”,“Name:“Me”}
在这里,serialiser看到您提供了一个派生类型,但该类型是“已知的”(即两端都知道可能需要的类型)。所以它会被类型提示序列化。你不需要再做什么了。框架为您处理所有这些
将KnownTypes放在任何地方都可能是一件麻烦事,因此DataContractJsonSerializer构造函数的另一个重载就在这里派上了用场,因此您可以在运行时而不是通过属性指定它们
希望这能有所帮助。但是在反序列化之前,你必须得到响应。TypeName
在某种程度上,包括对Json响应的另一个解析(或反序列化)。我在上面做了编辑并给出了更多反馈,因为我仍然遇到同样的问题。当我调试我的服务时,它甚至没有碰到我的任何代码,这告诉我我需要对我在合同中注册的对象(DataContract、KnownTypeAttribute等)做些什么,我不确定。@CitadelCSAlum:我不确定你想做的事情是否可行。WCF需要知道它正在序列化/反序列化的类型,你不能绕开它。也许你应该考虑在你的代码> SerialIsIsActudio/<代码>类中表示你的对象的其他方法?我已经做了上面的编辑,但是我仍然在运行同样的问题。在你的例子中,你根本不需要序列化类型“类型”。代码>字符串类型字符串=类型(字符串).Fullname
然后只序列化字符串(或包含字符串的类型)。如果您只是序列化request.type的数据,请省略serlialiser构造函数的第二个参数。新建DataContractJsonSerializer(类型)
应该足够感谢您的回复,但我认为您不了解正在做什么,在WCF服务中使用DataContractSerializer在从使用此服务的客户端传递类型时不会以这种方式工作。
var person = new Person { Name = "Me", Age = Int16.MaxValue.ToString() };
Console.WriteLine(Serialize<BaseObject>(person));
// Produces: {"__type":"Person:#ConsoleApplication6","Age":"32767","Name":"Me"}