gpt4 book ai didi

client-server - 向后兼容的服务接口(interface),无需更新 azure 服务结构中的旧客户端

转载 作者:行者123 更新时间:2023-12-03 16:19:30 25 4
gpt4 key购买 nike

我有一个服务结构有状态服务,它公开了一个接口(interface),例如:

public interface IAction 
{
Task GetCustomer (Customer customer)
}

客户类看起来像
[DataContract]
public class Customer
{
[DataMember]
public string Id {get;set;}

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

我现在已经通过 nuget 与服务的客户端共享了包含上述模型和接口(interface)的程序集。

过了一会儿,我需要为其他客户更新 Customer 类,所以我通过添加额外的可为空属性执行以下操作
[DataContract]
public class Customer
{
[DataMember]
public string Id {get;set;}

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

[DataMember]
public ulong? Salary {get;set;}
}

由于我添加了一个可为空的数据成员,我假设我只需要与较新的客户共享这个新模型和契约(Contract),而第一个客户不需要更新。

但是,我注意到我收到以下异常:
{"Interface id 'xxxxxxxx' is not implemented by object '**'"}

在阅读了多个 SO 答案( herehere )之后,我得出的结论是,客户端始终必须具有当前运行的服务版本中存在的接口(interface)和模型的准确引用。

这是一个很大的限制,因为我不应该被迫更新所有客户端。添加的额外可选参数不应强制更新旧客户端,尤其是在服务可以保证完全向后兼容性的情况下。

有没有办法以向后兼容的方式更新服务接口(interface)而无需更新旧客户端?

最佳答案

This is quite a big limitation, as I should not be forced to update all clients. Extra optional parameters added should not force the old clients to be updated, especially if the service can guarantee full backwards compatibility.



这根本不是限制,因为第一,服务不应该知道客户端,第二,操作/成员的添加不被认为是破坏,因为客户端不需要知道添加。

服务中的契约(Contract)更改被视为“ 非破坏性 ”。您共享的 SO 上其他类似问题的链接并未完全解决您的问题,可分为以下要点:
  • 服务发现
  • 服务版本控制
  • 实现 IExtensibleDataObject(如果问题是由新添加到服务的往返后的数据/数据类型引起的)

  • 1 & 2 大约是 发现服务的客户端正确地,使用您的服务的客户端需要注意它以实现宽松的版本控制兼容性,即 在调用您的服务之前,您需要确认客户端没有对旧服务执行任何模式验证 .如果是这种情况,那么您需要使用显式 XML 命名空间并定义新的契约(Contract)和新的服务定义。

    这是 不是限制但是要保持严格的版本控制,而且它还与早期客户端与您的服务绑定(bind)未知的数据类型有关,这些数据类型由于回调而出现异常,这是合理的,您应该接受它与 SOA 无关。

    要使用此解决方案,您可能需要通过以下方式定义契约(Contract)和服务:
    public interface IPurchaseOrderV1  
    {
    string OrderId { get; set; }
    string CustomerId { get; set; }
    }

    [DataContract(
    Name = "PurchaseOrder",
    Namespace = "http://examples.microsoft.com/WCF/2005/10/PurchaseOrder")]
    public class PurchaseOrderV1 : IPurchaseOrderV1
    {
    [DataMember(...)]
    public string OrderId {...}
    [DataMember(...)]
    public string CustomerId {...}
    }

    和新添加的成员的另一个版本,像这样,
    public interface IPurchaseOrderV2  
    {
    DateTime OrderDate { get; set; }
    }

    [DataContract(
    Name = "PurchaseOrder",
    Namespace = "http://examples.microsoft.com/WCF/2006/02/PurchaseOrder")]
    public class PurchaseOrderV2 : IPurchaseOrderV1, IPurchaseOrderV2
    {
    [DataMember(...)]
    public string OrderId {...}
    [DataMember(...)]
    public string CustomerId {...}
    [DataMember(...)]
    public DateTime OrderDate { ... }
    }

    这段代码的来源可以引用这篇 link这肯定会帮助您了解您的服务有什么问题以及如何修改它。

    只需将此作为事后的想法添加到 DataMember 的 isRequired 属性中,默认情况下为 false。

    以下引用自 here .

    If a default value of null or zero for the member is unacceptable, a callback method should be provided using the OnDeserializingAttribute to provide a reasonable default in case the member is not present in the incoming stream.


    [OnDeserialized]
    public void OnDeserialized(StreamingContext context)
    {
    if (this.id == null) throw new ArgumentNullException("id");
    if (this.Name == null) throw new ArgumentOutOfRangeException("name");
    if (this.Salary < 0) throw new ArgumentOutOfRangeException("salary");

    if (this.Salary > 0)
    {
    throw new InvalidOperationException("No child labor allowed");
    }
    }

    关于client-server - 向后兼容的服务接口(interface),无需更新 azure 服务结构中的旧客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48314135/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com