2

我们有一个巨大的客户端/服务器 WinForms 应用程序,它使用 .NET 远程处理在层之间传递 DAO,这有一些问题。

  1. 早在我来到这里之前,所有的 DAO 都被定义为使用字段而不是属性,并且您不能将字段绑定到控件。
  2. 向 DAO 添加字段或属性会更改序列化格式,需要双客户端/服务器部署,这对我们来说比客户端或服务器部署要困难得多(我们必须围绕医生的日程安排工作以最大限度地减少停机时间)。

使用一个简单的、人为的、虚构的例子,可以改变对象:

public class Employee
{
    public int ID;
    public string Name;
    public DateTime DateOfBirth;
}

对此:

public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
}

更改序列化格式,破坏与旧客户端的兼容性?

4

1 回答 1

1

重要编辑:这应该兼容并允许绑定?

public class Employee
{
    private int id;
    private string name;
    private DateTime dateOfBirth;
    public int ID { get {return id;} set {id = value;} }
    public string Name { get {return name;} set {name = value;} }
    public DateTime DateOfBirth { get {return dateOfBirth;}
         set {dateOfBirth = value;} }
}

当然值得一试,不是吗?

是的,如果客户端/服务器不同步,这将导致问题。

.NET 远程处理使用 BinaryFormatterm,它(没有定制ISerializable实现)使用字段名称。使用自动属性会破坏字段名称。

只要您同时更新客户端和服务器,它应该可以工作。另一种选择是使用与名称无关的序列化,例如protobuf-net。如果你愿意,我可以提供一个例子(它支持ISerializable使用)。

(顺便说一下,添加属性不应该影响BinaryFormatter因为它是基于字段的)


根据要求,这是使用protobuf-net控制远程序列化的示例(直接取自我的一个单元测试);请注意,在客户端和服务器都同意之前,这也是不兼容的,但应该承受之后的更改(它被设计为非常可扩展)。请注意,有很多使用它的方法 - 显式成员表示法(如数据合同)或隐式字段(如BinaryFormatter)等(介于两者之间的所有内容)......这只是使用它的一种方式:

[Serializable, ProtoContract]
public sealed class ProtoFragment : ISerializable
{
    [ProtoMember(1, DataFormat=DataFormat.TwosComplement)]
    public int Foo { get; set; }
    [ProtoMember(2)]
    public float Bar { get; set; }

    public ProtoFragment() { }
    private ProtoFragment(
        SerializationInfo info, StreamingContext context)
    {
        Serializer.Merge(info, this);
    }
    void  ISerializable.GetObjectData(
        SerializationInfo info, StreamingContext context)
    {
        Serializer.Serialize(info, this);
    }
}

在这里,底部的 2 个方法满足ISerializable,并简单地将执行传递给protobuf-net引擎。定义字段([ProtoMember(...)]带有唯一标识标记)。如前所述,它也可以推断出这些,但更安全(不那么脆弱)是明确的。

于 2009-02-09T15:49:47.263 回答