1

我在客户端看到以下场景的序列化问题。

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

[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; }
}

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

这个问题有什么解决方法吗?这破坏了对客户端的向后兼容性。

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

4

1 回答 1

0

使用上面的示例,我在派生类中重载了属性“B”并让它引用基类(我在 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

于 2015-10-07T02:02:55.887 回答