WCF RESTful Service, вопрос о сериализации с помощью DataContract.

2

Ситуация следующая: Есть класс сообщения, которое посылается или принимается сервером в теле Http-запроса:

[DataContract(Namespace = "")]
public class MyMessage
{    
   private JsonHead m_Head;

    [DataMember(Name = "Head")]
    public JsonHead Head
    {
        get { return m_Head; }
        set { m_Head = value; }
    }
}

В голову Head надо сувать различные дочерние классы в зависимости от ситуации. Вот абстрактный класс:

[DataContract(Namespace = "")]
[Serializable]
public abstract class JsonHead: ISerializable
{
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
 {}
}

Вот, к примеру, его наследник:

[DataContract(Name = "HashHead", Namespace = "")]
[Serializable]
public class HashHead : JsonHead
{
    private string m_RegId;
    private string m_Hash;

    [DataMember(Name = "RegistryId")]
    public string RegistryId
    {
        get { return m_RegId; }
        set { m_RegId = value; }
    }

    [DataMember(Name = "Hash")]
    public string Hash
    {
        get { return m_Hash; }
        set { m_Hash = value; }
    }


    public HashHead(string par1, string par2)
    {
        m_Hash = par1;
        m_RegId = par3;
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
       info.SetType(this.GetType());
    }
}

Метод на сервере, подстовляем в Head экземпляр класса HashHead вместо JsonHead :

 [OperationContract]
 [WebGet(UriTemplate = "Head1", ResponseFormat = WebMessageFormat.Json)]
    MyMessage GetJsonHead1()
{
        JsonMessage result = new JsonMessage();
        result.Head = new HashHead("test","test");
        return result;
}

В итоге возникает ошибка сериализации... Что я сделал не так, и возможно-ли реализовать мою задумку? По идее должен вызываться метод HashHead'а при сериализации и все должно быть гладко.

Лучший ответ:

2

Нужно использовать атрибут ServiceKnownType и применять его в интерфейсе сервиса (на сам интерфейс или на отдельный метод):

[OperationContract]
[ServiceKnownType(typeof(HashHead))]
[WebGet(UriTemplate = "Head1", ResponseFormat = WebMessageFormat.Json)]
    MyMessage GetJsonHead1()
{
    JsonMessage result = new JsonMessage();
    result.Head = new HashHead("test","test");
    return result;
}
Narmon

А вот это мысль. В зависимости от метода, будет сериализация к нужному типу. Как раз то, что надо! Спасибо!

Новые ответы

Шикарный придверный ковер b-sf.ru.
Новые Лучшие

2

Попробуй так:

[DataContract(Namespace = "")]
[KnownType(typeof(HashHead))]
[Serializable]
public abstract class JsonHead: ISerializable
{
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
 {}
}

KnownTypeAttribute Задает типы, которые должны распознаваться DataContractSerializer при сериализации или десериализации указанного типа.

Narmon

Увы, не помогло.:(

Да и KnownTypeAttribute, как я понял, предпологает жесткую превязку к одному типу?

alex.algel

KnownTypeAttribute можно указывать несколько раз с разными типами.


v1.7.123.556
© 2009—2010 CodeHelper FAQ | О сайте | Обратная связь | История изменений | Статьи
Creative Commons LicenseМатериалы сайта распространяются под лицензией Creative Commons Attribution-Share Alike 3.0 Unported.