将现有类属性移动到新创建的基类时的WCF序列化问题

时间:2013-08-14 23:41:42

标签: wcf soap

我在客户端看到了以下情况的序列化问题。

假设我们的服务代码中包含以下类和方法

[DataContract]
public class Derived
{
    [DataMember]
    public string A { get; set; }

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

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

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

并且服务接口具有方法

    [OperationContract]
    Derived GetDerived();

方法的实施 -

public Derived GetDerived()
{
    var d = new Derived() {A = "A", B = "B", C = "C", D = "D"};
    return d;
}

对于这个WCF服务,如果我创建客户端代理(通过添加服务引用)并执行GetDerived()调用,一切正常。

让我们稍微改变服务代码中的实体

[DataContract]
public class Base
{
    [DataMember]
    public string B { get; set; }
}

[DataContract]
public class Derived : Base
{
    [DataMember]
    public string A { get; set; }        

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

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

所以在这种情况下我创建了一个新的Base类并将属性'B'移动到Base类。在客户端使用相同的旧代理,如果我执行GetDerived调用,我看不到A在客户端正确序列化的值。但是,先前版本的SOAP消息和当前版本是相同的(仅更改了订单)。我遇到了这篇http://msdn.microsoft.com/en-us/library/ms729813.aspx文章解释了这个顺序。由于我将'B'移动到基类,我无论如何都不会在派生类中控制它的顺序。

这个问题有解决方法吗?这打破了与客户端的向后兼容性。

另一方面,如果我添加新属性,假设C1为Derived类(或任何现有类),它也会更改顺序。为什么这不打破客户?与我之前提到的情景相比。

1 个答案:

答案 0 :(得分:0)

使用上面的例子,我重载了属性" B"在派生类中,让它引用Base类(我在VB中工作,抱歉):

#region "This shenanigans prevents breaking the contract when moving some properties to the base class.
    <DataMember()> Public Overloads Property B() As String
        Get
            Return MyBase.B
        End Get
        Set(value As String)
            MyBase.B = value
        End Set
    End Property
#End Region

这样我的基类方法仍然可以在B上运行。如果我们开始实现wcf版本控制,或者还有其他需要更改契约,我可以去掉派生类中的重载,一切都应该只是工作

-JG