可以由调用者自定义的通用谓词?

Posted

技术标签:

【中文标题】可以由调用者自定义的通用谓词?【英文标题】:A generic predicate which can be customized by caller? 【发布时间】:2020-10-14 05:33:23 【问题描述】:

我有一堆这样定义的谓词,每个谓词检查不同的 http 状态代码:

readonly Predicate<HttpResponseData> createdHttpStatusPredicate = (HttpResponseData responseData) => 
    return responseData.StatusCode == HttpStatusCode.Created;
;

readonly Predicate<HttpResponseData> okHttpStatusPredicate = (HttpResponseData responseData) => 
    return responseData.StatusCode == HttpStatusCode.OK;
;

...

我像这样将它们传递到以下方法中(代码已经稍微简化以删除不相关的细节):

public static async Task<HttpResponseData> HttpCaller(HttpMethod requestMethod, Predicate<HttpResponseData> predicate)

    HttpResponseData response = await SendHttpRequest(requestMethod);

    if (predicate(response) == true)
        return response;
    else
        return null;

这是一个将一个谓词发送到上述方法的示例调用:

HttpResponseData data = await HttpRequestUtils.HttpCaller(HttpMethod.Post, createdHttpStatusPredicate);

我想知道,我是否可以将所有谓词组合到某个通用谓词中,或者以某种方式指定要在我调用 HttpCaller 时在谓词中查找的 http 状态?

是的,我知道上面的例子没有多大意义,因为我可以直接将我正在寻找的 http 状态传递给 HttpCaller 而无需通过谓词,但在我的情况下,HttpCaller 可以接收我的复杂的谓词也作为输入,基于从哪里调用HttpCaller

【问题讨论】:

如果我对问题的理解正确,您有两种情况:1. HttpCaller 被调用,Predicate 只检查 HttpStatus2. HttpCaller 以复杂的Predicate 调用。我对么?如果我是,为什么不使用两种方法HttpCaller:一种使用预期的HttpStatusarg,另一种使用Predicatearg? 所以 HttpCaller 方法处理许多不同的场景,因此接受许多不同的谓词,其中一些只测试特定的 http 状态......所以拥有多个方法没有意义做同样的事情 【参考方案1】:

接下来的两种方法可以用来去掉所有只检查HttpStatusCode的谓词。


1。创建一个为给定的HttpStatusCode 创建Predicate 的方法:

public static Predicate<HttpResponseData> CreatePredicateByHttpStatusCode(HttpStatusCode status)

    return r => r.StatusCode == status;

然后当你需要一个只检查给定HttpStatusCodePredicate时使用这个方法:

var result = await HttpCaller(httpMethod, CreatePredicateByHttpStatusCode(HttpStatusCode.OK));

2。创建方法 HttpCaller 的重载,它接受 HttpStatusCode 并且只检查给定的 HttpStatusCode

// This is your current method. It accepts a common Predicate that is used
// to check for complex conditions.
public static async Task<HttpResponseData> HttpCaller(HttpMethod requestMethod, Predicate<HttpResponseData> predicate)

    HttpResponseData response = await SendHttpRequest(requestMethod);

    if (predicate(response) == true)
        return response;
    else
        return null;


// This is a new Method. It accepts HttpStatusCode instead of the Predicate.
// It can be used for checking only for HttpStatusCode.
public static async Task<HttpResponseData> HttpCaller(HttpMethod requestMethod, HttpStatusCode status)

    // Here your original method HttpCaller is used.
    return await HttpCaller(requestMethod, r => r.StatusCode == status);

当您只需要检查HttpStatusCode时,可以使用HttpCaller的重载形式:

var result = await HttpCaller(httpMethod, HttpStatusCode.OK);

【讨论】:

您的第一个解决方案很棒,但是可以进一步减少...在您调用CreatePredicateByHttpStatusCode(HttpStatusCode.OK) 的地方,只需将其替换为r =&gt; r.StatusCode == HttpStatusCode.OK,然后您甚至不需要@ 987654337@方法:)

以上是关于可以由调用者自定义的通用谓词?的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义比较谓词的 heapq

如何从 Java 中的自定义谓词列表中创建一个谓词?

如何对实体的自定义属性进行谓词

使用自定义谓词对 numpy 数组进行排序

在 Json 自定义 ContractResolver 的 ShouldSerialize 谓词中获取请求

Android 图片选择器,丰富的配置选项,极大程度的简化使用