使用不同引用版本的客户端和服务器之间的序列化

时间:2011-09-09 17:19:17

标签: c# wcf serialization deserialization

我有一个引用包含以下类的程序集的Windows服务。

 [Serializable]
 public class User
    {
        public User(string userName)
        {
            UserName = userName;
        }

        public string UserName { get; private set; }
    }

此服务有一种方法可以让我们创建用户:

public User CreateUser(User user)
        {
        //Create and return user
    }

通过远程处理,我们可以在从我们的应用程序中获取User对象的服务中调用此方法。该应用程序引用该服务为User类执行的相同程序集,但它强制使用特定的1.0.0.0版本。

CreateUser(User user);

我们希望更改从每个项目引用的现有程序集,以向User类添加新属性“Phone”。

 [Serializable]
 public class User
    {
        public User(string userName)
        {
            UserName = userName;
        }

        public string UserName { get; private set; }
        **public string Phone { get; set; }**
    }

我们将汇编版本从1.0.0.0增加到2.0.0.0。 Windows服务将引用GAC中2.0.0.0版本的程序集。由于我们的某些客户端升级速度很慢,并且强制部署的特定版本或将其复制到本地,因此它们仍将引用1.0.0.0版本。

通过对服务程序集引用的这一更改,将对象从服务反序列化/序列化到应用程序的编组器会引发序列化错误。 “格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数时出错...”

我们所做的更改应该是一个非突破性的更改,因为我们刚刚添加了其他功能。有没有办法允许现有的应用程序继续使用1.0.0.0版本的程序集并将没有新属性的2.0.0.0序列化到它们而不对服务进行一些复杂的转换?

更新

我们正在使用以下内容连接到我们的服务

marshaller = ChannelFactory<T>.CreateChannel(new NetTcpBinding() { MaxReceivedMessageSize = MaxResponseSize }, new EndpointAddress(new Uri(new Uri(servers[serverIndex]), serviceName)));

内部异常: http://tempuri.org/:CreateUserResult。 InnerException消息是''EndElement''来自命名空间'http://tempuri.org/'的'CreateUserResult'不是预期的。期待元素'_someOtherField'。'。有关更多详细信息,请参阅InnerException ......下一个内部是空的

2 个答案:

答案 0 :(得分:2)

我怀疑,这是问题所在;

NetTcpBinding

(来自你的编辑)。基本上,WCF包括一些友好的契约支持,以及一些不太友好的基于类型的支持。

如果可能,我建议最简单的选择是不使用NetTcp ,因为它默认使用NetDataContractSerializer(基于类型),所以有版本问题。或者,您可以在传输上使用oter序列化程序 - 例如protobuf-net的DataContractSerializer。但是,改变这种情况本身就是一个突破性的变化。

我认为可以在NetDataContractSerializer中使用自定义活页夹 - 请参阅Problem deserializing with NetDataContractSerializer after refactoring code。如果你可以使用它,它应该保留API,但不应低估;我认为这将是一种维护负担,说实话。我宁愿减少损失,打破API 一次并切换到基于合同的序列化程序。

答案 1 :(得分:0)

也许OptionalField属性适合您,具体取决于格式化程序,请参阅http://msdn.microsoft.com/en-us/library/system.runtime.serialization.optionalfieldattribute.aspx