简体   繁体   English

DataContract序列化 - 我可以序列化Type属性吗?

[英]DataContract Serialization - Can I serialize a Type Property?

I am working on providing a generic JSON serialiation/deserialization service as a WCF service. 我正在努力提供通用的JSON序列化/反序列化服务作为WCF服务。

in order to do this, I have the following DataContract 为了做到这一点,我有以下DataContract

[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

}

The problem I am experiencing is I am getting the following error: 我遇到的问题是我收到以下错误:

The InnerException message was 'Type 'System.RuntimeType' with data contract name 'RuntimeType:http://schemas.datacontract.org/2004/07/System' is not expected. InnerException消息是'Type'System.RuntimeType',数据协定名称为'RuntimeType:http://schemas.datacontract.org/2004/07/System'不是预期的。 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.'. 考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。 Please see InnerException for more details. 有关更多详细信息,请参阅InnerException。

Which tells me I either need to make the DataContractJSONSerializer aware of the type, or that Type is unable to be serialized. 这告诉我,我需要让DataContractJSONSerializer知道该类型,或者该类型无法序列化。

I have tried registering the type of object and adding it to the Serializers "Known Types", but this doesn't seem to work, which makes me believe that my problem lies in having a parameter of type Type on my DataContract. 我已经尝试注册对象的类型并将其添加到Serializers“Known Types”,但这似乎不起作用,这让我相信我的问题在于我的DataContract上有一个Type类型的参数。

How can I accomplish this? 我怎么能做到这一点? I need to be able to call the following code("ish"). 我需要能够调用以下代码(“ish”)。

        DataContractJsonSerializer serializer = new DataContractJsonSerializer(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};

EDIT 编辑

I have changed the type parameter to be the Full Qualified Name of the type that is to be serialized, but I am still getting the same problem when I call the following code in my Remote WCF Service: 我已将类型参数更改为要序列化的类型的完全限定名称,但是当我在远程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};

I have tried adding that created type to the KnownTypes in the Constructor of the DataContractJSONSerializer, but that is not working either...any ideas? 我已经尝试将创建的类型添加到DataContractJSONSerializer的构造函数中的KnownTypes,但这不起作用......任何想法?

Here is an example of a simple class that would be called that needs to be able to be serialized 下面是一个需要能够序列化的简单类的示例

[DataContract]
[KnownType(typeof(Person))]
public class Person
{
    [DataMember]
    public string Age {get;set;}

    [DataMember]
    public strign Name {get;set;}
}

so now I should be able to pass this into my request object with specifying the type name, and then get back a JSON Result of this object. 所以现在我应该能够通过指定类型名称将它传递给我的请求对象,然后返回此对象的JSON结果。

I'm not sure why you need the .NET type in JSON, but you can serialise the Type to a string and then obviously create a Type from a string. 我不确定为什么你需要JSON中的.NET类型,但你可以将Type序列化为字符串,然后显然从字符串创建一个Type。

You can use the Type.FullName and Assembly.GetType("My.Type") to get the string (serialise) and create Type from the name (deserialise). 您可以使用Type.FullName和Assembly.GetType(“My.Type”)来获取字符串(序列化)并从名称(反序列化)创建类型。

You're making this way too hard. 你这么做太难了。

Given the following: 鉴于以下内容:

[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;
}

You can serialise a Person: 你可以序列化一个人:

        var person = new Person { Name = "Me", Age = Int16.MaxValue.ToString() };
        Console.WriteLine(Serialize<Person>(person));
        // Produces: {"Age":"32767","Name":"Me"}

In this case the serialiser is working on the basis that the can be deserialised to a single known type. 在这种情况下,序列化器的工作基础是可以将其反序列化为单个已知类型。 Whoever is going to be pulling this data back out knows what to expect, so the type does not get pushed in. 无论谁将这些数据拉出来都知道会发生什么,所以这种类型不会被推入。

Or you can serialize a BaseObject: 或者您可以序列化BaseObject:

    var person = new Person { Name = "Me", Age = Int16.MaxValue.ToString() };
    Console.WriteLine(Serialize<BaseObject>(person));
    // Produces: {"__type":"Person:#ConsoleApplication6","Age":"32767","Name":"Me"}

Here the serialiser sees that you're providing a derived type but that type is 'Known' (ie both ends know the possible types to expect). 在这里,序列化程序看到您提供了派生类型,但该类型是“已知”(即两端都知道可能的类型)。 So it gets serialized with the type hint. 因此它使用类型提示进行序列化。 You don't need to do anything more. 您不需要再做任何事情了。 The framework handles it all for you. 该框架为您处理所有这些。

Putting KnownTypes everywhere can be a pain in the butt, so that's where the other overload for the DataContractJsonSerializer constructor comes in handy, so you can specify them at runtime rather than via attributes. 将KnownTypes放在任何地方都可能是一个痛苦的问题,因此DataContractJsonSerializer构造函数的另一个重载派上用场,因此您可以在运行时而不是通过属性指定它们。

Hope that helps. 希望有所帮助。

You can't work with Type itself, because at runtime it will be an instance of RuntimeType - which is internal class and therefore cannot be added to ServiceKnownType attribute (or to be more precise - cannot be serialized by DataContractSerializer used by WCF). 您无法使用Type本身,因为在运行时它将是RuntimeType一个实例 - 它是内部类,因此无法添加到ServiceKnownType属性(或更准确地说 - 不能由WCF使用的DataContractSerializer序列化)。

You should considering serializing type's assembly qualified name as a simple string. 您应该考虑将类型的程序集限定名称序列化为一个简单的字符串。 This will allow you to recreate type on client side: 这将允许您在客户端重新创建类型:

[DataContract]
public class SerializationRequest
{
     // ...

     [DataMember]
     public string TypeName {get;set;}
}

// ...

var type = Type.GetType(response.TypeName);
var serializer = new DataContractJsonSerializer(type);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 DataContract“Type”属性的序列化 - DataContract serialization of property of “Type” 我可以将WCF DataContract添加到复杂类型吗? - Can I add a WCF DataContract to a complex type? DataContract将继承类型序列化为基类型 - DataContract serialization of an inherited type into a base type 如何覆盖属性的 JSON 序列化,以将值序列化为字符串而不是 object? - How can I override the JSON serialization for a property, to serialize the value as a string instead of an object? 当一个属性可以具有不同的类型时,如何序列化DataContract的Member? - How to serialize a DataContract's Members when one property can have different types? 数据合同与图像的序列化/序列化 - Datacontract serialization/serialization with images 子属性中的DataContract父引用-如何避免无限序列化循环 - DataContract Parent reference in child property - how to avoid infinite serialization loop 类型列表的属性 <Object> 在DataContract类中失败 - Property of type List<Object> in DataContract class fails C#XML序列化,我可以序列化列表 <T> ? - C# XML Serialization, Can I serialize List<T>? 如何序列化列表 <T> c#中的属性,但未在XML序列化中显示其类型 - How to Serialize List<T> property in c# without showing its type in XML serialization
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM