c# - 如何重写 Regex.Replace(由于异步 api)

标签 c# regex async-await

我有一个函数 ReplaceParameters,它使用 Regex.Replace 替换字符串中的值。这一直工作正常,但现在获取替换字符串的 api 已变为仅异步。这是当前代码的重现:

public static string ReplaceParameters(string query)
{
    var result = Regex.Replace(query, @"(?<parameter>\|\w+\|)", ReplaceParameterEvaluator,
                                         RegexOptions.ExplicitCapture);

    return result;
}

private static string ReplaceParameterEvaluator(Match parameterMatch)
{
    var parameter = parameterMatch.Groups["parameter"].Value;
    return GetReplacement(parameter);
}

private static string GetReplacement(string parameter)
{
    //...
}

因为(新的)GetReplacement 函数现在返回一个任务而不是字符串:private static async Task<string> GetReplacementAsync(string parameter) ReplaceParameterEvaluator 函数无法与 MatchEvaluator 委托(delegate)兼容。

因为这必须在网络服务器上运行并且不会导致死锁,所以我不能使用任何肮脏的异步到同步黑客,例如:(使用.Result)var replacedQuery = Regex.Replace(query, @"(?<parameter>\|\w+\|)", match => ReplaceParameterEvaluatorAsync(match).Result, RegexOptions.ExplicitCapture);

是否可以重写函数来查找所有文本,然后替换它们?可以以某种方式使用 Regex.Matches 吗?

(说真的,为什么没有 Regex.ReplaceAsync 函数??)

最佳答案

为此构建您自己的扩展方法非常简单:

public static async Task<string> ReplaceAsync(this Regex regex, string input, Func<Match, Task<string>> replacementFn)
{
    var sb = new StringBuilder();
    var lastIndex = 0;

    foreach (Match match in regex.Matches(input))
    {
        sb.Append(input, lastIndex, match.Index - lastIndex)
          .Append(await replacementFn(match).ConfigureAwait(false));

        lastIndex = match.Index + match.Length;
    }

    sb.Append(input, lastIndex, input.Length - lastIndex);
    return sb.ToString();
}

很简单:

  • 将不匹配的文本 block 按原样复制到 StringBuilder
  • 在文本匹配的地方追加回调函数的结果

这只是调用异步回调的便捷方法。它不在 API 中,因为正则表达式匹配和替换是 CPU 绑定(bind)操作,自然不是异步的。

关于c# - 如何重写 Regex.Replace(由于异步 api),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33014011/

相关文章:

regex - 使用 RegEx 解析 Transact SQL

c# - 如何正确解析 SQL CREATE TABLE 语句

javascript - 数组返回 0 的长度,尽管它有值

c# - 无法在 VS 2017 15.5.7 中添加服务引用

c# - 从 PageMethod 触发下载。哪里不对?

c# - 假 DataRepository - 模拟数据库

c# - 如何在事务上设置挂起的回滚?

javascript - 如何检测两点之间输入的数字

javascript - 自动执行异步函数

c# - 如何在循环中使用 await