WCF - 入站多态数组(datacontract的属性)未正确反序列化

时间:2013-05-07 16:54:16

标签: wcf datacontractserializer

以下是问题的简化。

我有Type Bar,Bar1和Bar2的DataContracts。

[DataContract]
[Serializable]
[KnownType(typeof(Bar1))]
[KnownType(typeof(Bar2))]
public class Bar
{
    Public int SomeVal{get;set;}
}

[DataContract]
[Serializable]
public class Bar1: Bar
{
     Public int SomeOtherVal{get;set;}
}

[DataContract]
[Serializable]
public class Bar2: Bar
{
     Public int YetAnotherOtherVal{get;set;}
}

我有第二个Type Foo的DataContract,它有一个公共属性List。 e.g。

[DataContract]
[Serializable]
public class Foo
{
    Public List<Bar> Bars {get;set;}

}

我有一个ServiceContract(接口),它有两个支持SOAP和JSON的方法。

[ServiceContract]
public interface IFooWorld
{
    [OperationContract]
    [WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat =    WebMessageFormat.Json)]
    [ServiceKnownType(typeof(Bar1))]
    [ServiceKnownType(typeof(Bar2))]
    Foo GetFoo();

    [OperationContract]
    [WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat =  WebMessageFormat.Json)]
    [ServiceKnownType(typeof(Bar1))]
    [ServiceKnownType(typeof(Bar2))]
    void SetFoo(Foo foo);
}

使用SOAPUI,我可以确认GetFoo正在返回阵列中混合了Bar1和Bar2对象的多态数组。

使用日志记录,我了解到当我在Foo.Bar中使用混合数组的Bar1和Bar2对象调用SetFoo时,Bar本身不为null,但它是空的。

我在SOAP中有各种样式的Bar参数

样式1 - 这导致入站Bar数组被分配但是空

<ns:Bars>
    <ns:Bar1>...
    </ns:Bar1>
    <ns:Bar2>...
    </ns:Bar2>
</ns:Bars>

样式2 - 这导致入站Bar数组具有Bar类型的项目,而不是Bar1和Bar2

<ns:Bars>
    <ns:Bar i:type="Bar1">...
    </ns:Bar>
    <ns:Bar i:type="Bar2">...
    </ns:Bar>
</ns:Bars>

这些都不起作用。关于如何在DataContract中为SOAP和JSON中的入站调用支持这种多态的任何建议?

1 个答案:

答案 0 :(得分:1)

您在数据类的每个属性上都缺少[DataMember]。 DataContractSerialiser是一个可选的序列化服务器,这意味着您需要选择加入该属性。

这样改变你的课程。

    [DataContract]
    [Serializable]
    [KnownType(typeof(Bar1))]
    [KnownType(typeof(Bar2))]
    public class Bar
    {
        [DataMember]
        Public int SomeVal{get;set;}
    }

    [DataContract]
    [Serializable]
    public class Bar1: Bar
    {
        [DataMember]
        Public int SomeOtherVal{get;set;}
    }

    [DataContract]
    [Serializable]
    public class Bar2: Bar
    {
        [DataMember]
        Public int YetAnotherOtherVal{get;set;}
    }


    I have a second DataContract of Type Foo, which has a public property, List<Bar>.
    e.g.
    [DataContract]
    [Serializable]
    public class Foo
    {
        [DataMember]
        Public List<Bar> Bars {get;set;}

    }