You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需修改中间方法,如何向Match的Left Lambda传递额外数据?

解决方案

方案1:拆分流程为两个阶段(推荐,无需修改底层方法)

把获取发卡机构(CardIssuer)的逻辑单独抽离,先处理这一步的错误;拿到合法的CardIssuer后,再执行后续的交易查询和状态获取,此时后续所有错误都能使用已获取的密钥加密。

代码实现:

static async Task<string> Process(string cardIssuerId)
{
    // 第一阶段:获取发卡机构,处理无密钥的错误场景
    var issuerEither = await GetCardIssuer(cardIssuerId).ToAsync();
    return await issuerEither.Match(
        async issuer =>
        {
            // 第二阶段:已拿到密钥,后续所有错误都可以用该密钥加密
            var transactionIdEither = await GetLatestTransactionId(issuer).ToAsync();
            return await transactionIdEither.Match(
                async transactionId =>
                {
                    var statusEither = await GetCustomerStatus(transactionId).ToAsync();
                    return statusEither.Match(
                        status => Encrypt(status.ToString(), issuer.Key),
                        error => Encrypt($"Error: {error}", issuer.Key)
                    );
                },
                error => Encrypt($"Error: {error}", issuer.Key)
            );
        },
        // GetCardIssuer失败时无密钥可用,直接返回原始错误
        error => Task.FromResult($"Error: {error}")
    );
}

该方案优势:

  • 完全不需要修改任何底层的Either返回方法,避免污染可复用逻辑
  • 逻辑清晰,明确区分“无密钥”和“有密钥”的错误场景
  • 代码改动最小,仅调整Process方法的结构

方案2:自定义带上下文的Either类型(适合长期复用)

如果你的代码中有大量类似场景需要携带上下文(比如密钥),可以自定义带上下文的Either类型,封装上下文传递逻辑,避免重复编写嵌套Match。

步骤1:定义带上下文的Either类型及扩展方法

// 携带上下文的Either类型,保留上下文和原始Either结果
record EitherWithContext<TContext, TLeft, TRight>(TContext Context, Either<TLeft, TRight> Either);

// 扩展方法:将普通Either转换为带上下文的Either
static EitherWithContext<TContext, TLeft, TRight> WithContext<TContext, TLeft, TRight>(
    this Either<TLeft, TRight> either, 
    TContext context)
    => new EitherWithContext<TContext, TLeft, TRight>(context, either);

// 扩展方法:实现Bind操作,保留上下文传递
static EitherWithContext<TContext, TLeft, TRightNew> Bind<TContext, TLeft, TRight, TRightNew>(
    this EitherWithContext<TContext, TLeft, TRight> eitherWithContext,
    Func<TRight, Either<TLeft, TRightNew>> bindFunc)
    => new EitherWithContext<TContext, TLeft, TRightNew>(
        eitherWithContext.Context,
        eitherWithContext.Either.Bind(bindFunc));

// 扩展方法:转换为异步类型(按需实现)
static async Task<EitherWithContext<TContext, TLeft, TRight>> ToAsync<TContext, TLeft, TRight>(
    this EitherWithContext<TContext, TLeft, TRight> eitherWithContext)
    => eitherWithContext;

步骤2:在Process方法中使用

static async Task<string> Process(string cardIssuerId)
{
    var issuerEither = await GetCardIssuer(cardIssuerId).ToAsync();
    return await issuerEither.Match(
        async issuer =>
        {
            // 链式调用时携带issuer上下文
            var resultWithContext = await GetLatestTransactionId(issuer)
                .WithContext(issuer)
                .Bind(transactionId => GetCustomerStatus(transactionId))
                .ToAsync();
            
            // 统一处理成功/错误,均可用上下文密钥加密
            return resultWithContext.Either.Match(
                status => Encrypt(status.ToString(), resultWithContext.Context.Key),
                error => Encrypt($"Error: {error}", resultWithContext.Context.Key)
            );
        },
        error => Task.FromResult($"Error: {error}")
    );
}

该方案优势:

  • 上下文传递逻辑封装在类型和扩展方法中,业务代码更简洁
  • 适合多个场景复用,避免重复编写嵌套Match逻辑

关键说明

如果GetCardIssuer本身返回Left(获取发卡机构失败),此时根本没有可用的加密密钥,只能返回未加密的错误信息——这是合理的,因为密钥依赖于成功获取的CardIssuer实例,获取失败自然无法进行加密操作。

内容的提问来源于stack exchange,提问作者Avrohom Yisroel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:20:33