我如何获得DataContractJsonSerializer序列化从接口泛型类时,在类型提示使用的

2019-09-27 04:33发布

我有一组类,如下所示:一个命令,该命令执行和存储结果; 一个回应,这是因为为了在序列化格式(加上我已经离开了额外的元数据)返回的结果产生。 所述Response.Result 必须是类型的对象,因为它是用于很多不同的命令,其中的每一个可以具有任何类型的结果在所有的。

该命令是通用的,我想它接受一个接口,而不是具体的类型,但是当我做,序列化的响应包含以下类型的提示:

  “__type”: “ResultOfanyType:#serialization” 

而不是下面,这是当所述命令接受一个具体类型产生的:

"__type":"ResultOfMyObjectDhOQ6IBI:#serialization"

我需要的那种类型的提示包含的具体类型而不是ResultOfanyType。 为什么接口被区别对待在这种情况下? 请注意,当Type是序列化指令的直接属性,然后具体类型包含在类型提示

我试图改变输入至Result的结果的响应特性,但没有效果。

下面是代码。 简单地取消注释/注释其中创建和已知的用于替代版本中列出类型的命令在主线路。

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

Answer 1:

让我们先从这个问题,这或许可以解释一切。

我需要的那种类型的提示包含的具体类型而不是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你有什么期待回来吗? 一个Person或一个Contact ? 每个人都有一个ID和名称的基本组成部分,但每个也有独特的性能IPerson甚至不知道存在。 这就是为什么当你试图去解决一个具体类的接口,你就不会取得任何没有某种工厂类弄清楚你想要什么。 所以在这种情况下,如果我想解决一个IPerson ,我要补充下面的代码行...

var objectType = iPersonObject.GetType();

在你的情况,你会想尝试调用GetType()result.Item 。 这告诉.NET来看看实际类型实现接口的对象,并返回。



Answer 2:

这个怎么样...

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

输出...

{"__type":"Response:#ConsoleApplication2","ResponseStatus":"ok","Results":{"__ty
pe":"ResultOfanyType:#ConsoleApplication2","Item":{"__type":"MyObject:#ConsoleAp
plication2","name":"my object"},"Status":"ok"}}

如果你想使某种通用的合同,你将必须有某种共同的基类/接口。 它不会与对象工作,但你可以去ALA COM,并从自己的IUnknown接口,只要你喜欢,因为它们都包含您的已知类型中创建任意多个子类,只要。



文章来源: How do I get DataContractJsonSerializer to use concrete type in type hint when serializing generic class from interface