使用DataContractSerializer序列化接口列表 [英] Serializing a List of Interfaces using the DataContractSerializer

查看:202
本文介绍了使用DataContractSerializer序列化接口列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,其中有一些嵌套类。我将它序列化并使用没有问题的方法将其发送到wcf服务。这是课程;

I have a class and there are some nested classes within it. I serialize it and send it to the wcf service using a method with no problems. Here's the class;

public class ComputerDTO
{
    [DataMember]
    public ComputerTypeDTO Type { get; set; }

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

    [DataMember]
    public MonitorDTO Monitor { get; set; }
}

这是方法;

public void Check()
{
    Computer c = new Computer();

    ISystemInfoOperations cli = GetServiceClient();

    Mapper.CreateMap<Monitor, MonitorDTO>();
    Mapper.CreateMap<IHardwarePart, IHardwarePartDTO>();

    Mapper.CreateMap<Computer, ComputerDTO>()
            .ForMember(s => s.Hardware, m => m.MapFrom(q => Mapper.Map<List<IHardwarePart>, List<IHardwarePartDTO>>(q.Hardware)));


    Mapper.AssertConfigurationIsValid();

    ComputerDTO dto = Mapper.Map<Computer, ComputerDTO>(c);

    string sendComputerInfo = cli.SendComputerInfo(dto);
}

但是我还有一个要发送的接口列表。所以我更改下面的代码并得到错误。

But I have also a list of interface to be sent. So I change the code like below and get an error.

public class ComputerDTO
{
    [DataMember]
    public ComputerTypeDTO Type { get; set; }

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

    [DataMember]
    public MonitorDTO Monitor { get; set; }

    [DataMember]
    public List<IHardwarePartDTO> Hardware { get; set; }
}

public interface IHardwarePartDTO
{
    [DataMember]
    string Name { get; set; }

    [DataMember]
    HardwarePartTypeDTO PartType { get; set;  }
}

硬件内部正在填补项目内容。但如果我尝试发送它,我会收到这个着名的错误:

Inside of hardware is getting filled in the project. But if I try to send it, I get this famous error :


输入
'代理''b $ b包含数据合同名称
'_x0030__Culture_x003D_neutral_PublicKeyToken_x003D_null_x003E_: http ://schemas.datacontract.org/2004/07/Proxy%3CSystemInfo.DTO.IHardwarePartDTO_SystemInfo.DTO_Version=1.0.0 '
不是预期的。考虑使用DataContractResolver或将已知静态未知的任何
类型添加到已知类型列表中 - 例如,使用KnownTypeAttribute属性
或将它们添加到传递给已知类型的
列表中DataContractSerializer。

Type 'Proxy' with data contract name '_x0030__Culture_x003D_neutral_PublicKeyToken_x003D_null_x003E_:http://schemas.datacontract.org/2004/07/Proxy%3CSystemInfo.DTO.IHardwarePartDTO_SystemInfo.DTO_Version=1.0.0' is not expected. 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.


推荐答案

DataContractSerializer需要了解可能返回的具体类型。接口无法序列化,因为它无法反序列化(如何在没有具体实现的情况下创建接口实例)。

The DataContractSerializer needs to know about the concrete types that is might return. An interface cannot be serialized, as it cannot be deserialized (how can you create an instance of an interface without a concrete implementation).

简单的解决方案是添加KnownTypes属性如下所示:

The simple resolution is to add KnownTypes attribute like below:

[KnownType(typeof(your hardware dto concrete type here))]
public class ComputerDTO
{
    [DataMember]
    public ComputerTypeDTO Type { get; set; }

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

    [DataMember]
    public MonitorDTO Monitor { get; set; }

    [DataMember]
    public List<IHardwarePartDTO> Hardware { get; set; }
}

您可以根据需要添加任意数量的已知类型属性。

You can add as many known type attributes as you like.

ServiceKnownTypes属性稍微复杂一些。这非常相似,但您可以将其添加到服务类中。

Slightly more complex is the ServiceKnownTypes attribute. This is very similar but you would add it to your service class.

除此之外,您可以使用数据合约解析程序 - 但这非常复杂,需要一段时间解释。

Other than that you can use a data contract resolver - but this is very complicated and would take a while to explain.

编辑:18/02/2013 15:11

18/02/2013 15:11

您可能还需要查看Automapper,因为它当前将在您的硬件列表中创建代理 - 并且代理无法序列化。您需要告诉automapper将它们序列化的内容 - 例如:

You may also need to look at you Automapper as its currently going to create proxies in your Hardware list - and proxies cannot be serialized. You need to tell automapper what to serialize them to - for example:

Mapper.CreateMap<Monitor, MonitorDTO>();
Mapper.CreateMap<Monitor, IHardwarePartDTO>().As<MonitorDTO>();

Mapper.CreateMap<Audio, AudioDTO>();
Mapper.CreateMap<Audio, IHardwarePartDTO>().As<AudioDTO>();

Mapper.CreateMap<CDROMDrive, CDROMDriveDTO>();
Mapper.CreateMap<CDROMDrive, IHardwarePartDTO>().As<CDROMDriveDTO>();
//you need entries like these for everythin that implements IHardwarePartDTO

这样自动化器知道什么它需要创建。

This way automapper knows what it needs to create.

这篇关于使用DataContractSerializer序列化接口列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆