【问题标题】:WCF Versioning EnumsWCF 版本控制枚举
【发布时间】:2011-01-13 07:52:08
【问题描述】:

我开始编写一些需要前向兼容和版本控制的 WCF 数据协定。我一直在阅读 MSDN 文章 here,并想知道是否有人对第 14 点关于枚举的澄清。内容如下:

14.您不应该在版本之间添加或删除枚举成员。您也不应该重命名枚举成员,除非您使用 EnumMemberAttribute 属性上的 Name 属性来保持它们在数据协定模型中的名称相同。

阅读本文,我认为它的意思是一旦枚举发布(并被客户端使用),您就不能在不破坏兼容性的情况下以任何方式修改它(主要是添加/删除)? (即这将是一个突破性的变化)

有人可以确认吗?

【问题讨论】:

  • 添加枚举成员不会破坏功能,但如果枚举成员正在使用,则删除会。当且仅当服务实现发生更改或添加新的服务合同时,添加才会有用。

标签: .net wcf enums versioning


【解决方案1】:

我建议不要通过 WCF 接口发送枚举。假设你有以下枚举:

[DataContract]
public enum WeekdayEnum
{
    [EnumMember]
    Monday = 0
}

如果您通过 WCF 返回枚举,一切都会正常运行:

[ServiceContract]
public class Service1
{
    [OperationContract]
    public List<WeekdayEnum> GetWeekdays()
    {
        return new List<WeekdayEnum> { WeekdayEnum.Monday };
    }
}

添加到枚举而不更新客户端中的服务引用,你仍然可以:

[DataContract]
public enum WeekdayEnum
{
    [EnumMember]
    Monday = 0,
    [EnumMember]
    Tuesday = 1
}

但是,如果您从服务返回附加值而不更新客户端服务引用,旧客户端将中断

[ServiceContract]
public class Service1
{
    [OperationContract]
    public List<WeekdayEnum> GetWeekdays()
    {   // NetDispatcherFaultException on legacy clients that only have Monday
        return new List<WeekdayEnum> { WeekdayEnum.Monday, WeekdayEnum.Tuesday };
    }
}

在支持遗留客户很重要的项目中,我遇到了这个问题。解决方案是简单地通过 WCF 而不是枚举发送 DTO。例如。可以通过简单的 DTO 发送值来替换 WeekdayEnum:

[DataContract]
public class WeekdayDto
{
    [DataMember]
    public int Id { get; set; }

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

这样,您的老客户会很开心。

【讨论】:

  • 不确定是否跟随。您是说您宁愿处理“List”而不是 List
  • 处理枚举更容易。如果枚举随时间变化,旧客户端将中断(您需要更新它们)。如果枚举从不更改,或者您可以确保在枚举更改时始终更新所有客户端,那么应该没有问题。免责声明:已经有一段时间没有使用 WCF。
  • 好的,但是在枚举发生变化的情况下,您宁愿创建一个 List?那正确吗?或者你有什么不同的想法?
  • 是的,我就是这样做的。
【解决方案2】:

我可以确认您可以添加到已发布的枚举而不破坏兼容性,只要您在与服务通信时不使用新值。但是请注意,如果您实际上尝试向使用新枚举值的服务发送一个类,您将收到 System.ServiceModel.CommunicationException。

There was an error while trying to serialize parameter myType. The InnerException message was 'Enum value 'x' is invalid for type 'myType' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'.  Please see InnerException for more details.

【讨论】:

  • 如果服务返回一个包含附加值的枚举类型列表给旧客户端,这是真的吗?
  • @JeremyRosenberg 是的,同样的问题