如何从服务中返回各种类型的产品,但具有相同的部分

本文关键字:服务 返回 类型 种类 | 更新日期: 2023-09-27 18:35:23

我从我的服务中返回各种类型:

[ServiceContract]
public interface IService
{
    [OperationContract]
    void Initialize();
    [OperationContract]
    Settings GetSettings(); // returns custom type Settings
    [OperationContract]
    void SetSettings(Settings settings);
    [OperationContract]
    bool SettingsAccepted();
}

但是,我想为我的服务引入状态代码,该代码不是基于 WCF 基础结构构建的,而是基于我的服务的内部逻辑构建的,如下所示:

[DataContract]
public enum ServiceStatus
{
    [EnumMember]
    NormalWork = 0,
    [EnumMember]
    TimeOut,
    [EnumMember]
    DenialOfService
};

我希望我的服务不仅返回 void、bool 或自定义类型,还返回带有状态代码的它们,如下所示(伪代码):

[ServiceContract]
public interface IService
{
    [OperationContract]
    (ServiceStatus) Initialize();
    [OperationContract]
    (ServiceStatus, Settings) GetSettings();
    [OperationContract]
    (ServiceStatus) SetSettings(Settings settings);
    [OperationContract]
    (ServiceStatus, bool) SettingsAccepted();
}

客户端的逻辑是这样的:检查返回消息中的状态代码,如果是ServiceStatus.NormalWork,则使用返回消息的其余部分。

如何最好地组织它?我是否引入了要返回的基类(使用 DataContract 属性),然后根据每个返回值(每个操作协定)从中创建新的派生类?还是有更好的方法?也许 WCF 中有一个内置的基础结构用于这样的任务 - 将自定义状态代码与自定义返回类型一起返回?

如何从服务中返回各种类型的产品,但具有相同的部分

客户端的逻辑是这样的:检查返回消息中的状态代码,如果是ServiceStatus.NormalWork,则使用返回消息的其余部分。

如果你真的想要这个,另一个答案有创造这样一个野兽的所有细节。但是,请不要这样做。如果服务无法正常工作,请引发异常。它将自动转换为故障。

返回代码是 1980 年。我已经必须进行异常处理。您的服务可能不可用,网络可能已关闭或可能存在任何其他故障。所以我已经有了异常处理,现在使用您提出的方法,我需要异常处理返回代码处理。每一次通话。糟糕透了。此外,人们可能会更容易犯错误。他们可能只是获取传递的值,而忘记检查您的返回代码。除了例外,这个错误永远不会发生。

如果您希望您的服务失败并显示"拒绝服务"的错误,那么请创建一个DenialOfServiceException并将其抛出。不要使用返回代码。这不是 WCF 报告错误的方式。


如果你确实想要一个固定的结构,你可以使用另一个答案的模板方法,或者你可以使用继承:

[DataContract]
public class ServiceResponse
{
    [DataMember]
    public ServiceStatus Status { get; set; }
}
[DataContract]
public class SettingsAcceptedResponse : ServiceResponse
{
    [DataMember]
    public bool Result { get; set; }
}
[ServiceContract]
public interface IService
{
    // [...] 
    [OperationContract]
    ServiceResponse SetSettings(Settings settings);
    [OperationContract]
    SettingsAcceptedResponse SettingsAccepted();
}

您可以尝试创建名为 ServiceResponse<T> 的类,并且使用属性,您需要具有 T 类型的状态和属性,其中将是真正的返回对象。

当然,在这种方法中,当结果类型为bool时,所有方法都将返回ServiceResponse<bool>

它可能看起来像这样:

[DataContract]
public class ServiceResponse<T>
{
  [DataMember]
  ServiceStatus Status { get; set; }
  [DataMember]
  T Payload { get; set; }
}

此类还可以包含发送给用户的消息、异常、错误以及可用于正确处理来自 WCF 的响应的任何内容。

那么在 WCF 中的用法将是:

[OperationContract]
    ServiceResponse<bool> SettingsAccepted();