Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DataContract序列化-我可以序列化类型属性吗?_C#_Json_Wcf - Fatal编程技术网

C# DataContract序列化-我可以序列化类型属性吗?

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

我正在致力于提供一个通用的JSON序列化/反序列化服务作为WCF服务

为了做到这一点,我有以下数据合同

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