Serializing a List of Interfaces with DataContractSerializer

I have a class and inside it there are several nested classes. I am serializing it and sending it to wcf service using no problem method. 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; }
}

      

Here's the method:

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 also have a list of interfaces to send. So I change the code as shown below and I get the 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 the equipment, a project is being filled. But if I try to post it, I get this known error:

Type 'Proxy' with data contract name '_x0030__Culture_x003D_neutral_PublicKeyToken_x003D_null_x003E_: http://schemas.datacontract.org/2004/07/Proxy%3CSystemInfo.DTO.IHardwarePartDTO_SystemInfo1.DTO_Vers ' not expected. Consider using the DataContractResolver, or add types that are not statically known 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 the DataContractSerializer.

+3


source to share


1 answer


The DataContractSerializer needs to be aware of the specific types that can be returned. An interface cannot be serialized because it cannot be deserialized (how to instantiate an interface without a specific implementation).

A simple resolution is to add the KnownTypes attribute as shown 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.

The ServiceKnownTypes attribute is a little more complex. This is very similar, but you would add it to your class of service.



Alternatively, you can use a contract data recognizer - but it is very difficult and will take some time to explain.

EDIT: 18/02/2013 15:11

You might also need to look at Automapper as it is currently going to create proxies in your hardware list and proxies cannot be serialized. You have to tell the automapper what to serialize them for, 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.

+5


source







All Articles