如何简化带6个泛型参数的MVC API Service基类实现?
优化MVC API服务基类的泛型参数方案
核心优化思路
把Check、Pay、PayStatus这三个操作各自的请求、响应额外参数,分别打包成独立的参数组,再通过一个统一的接口把这三个参数组聚合在一起。这样服务基类只需要接收一个泛型参数,就能关联所有操作的参数类型,彻底摆脱原来6个泛型参数的冗余和繁琐。
具体实现步骤
1. 抽离通用的基础请求/响应类
把三个操作共有的属性(比如商户ID、请求ID、响应状态码这些)抽成基类,避免重复代码:
// 所有请求的基础父类 public abstract class BaseServiceRequest { public string MerchantId { get; set; } public string RequestId { get; set; } public long Timestamp { get; set; } // 其他通用属性,比如签名、版本号等 } // 所有响应的基础父类 public abstract class BaseServiceResponse { public bool Success { get; set; } public string ErrorCode { get; set; } public string ErrorMessage { get; set; } }
2. 用接口聚合各操作的参数类型
定义一个统一的接口声明三个操作的参数类型,再写一个泛型类实现该接口,用来传递具体的参数类型:
// 统一的服务参数接口,明确三个操作的参数类型 public interface IServiceParams { Type CheckReqExtraType { get; } Type CheckRespExtraType { get; } Type PayReqExtraType { get; } Type PayRespExtraType { get; } Type PayStatusReqExtraType { get; } Type PayStatusRespExtraType { get; } } // 泛型实现类,绑定具体的参数类型 public class ServiceParams<TCheckReq, TCheckResp, TPayReq, TPayResp, TPayStatusReq, TPayStatusResp> : IServiceParams where TCheckReq : class where TCheckResp : class where TPayReq : class where TPayResp : class where TPayStatusReq : class where TPayStatusResp : class { public Type CheckReqExtraType => typeof(TCheckReq); public Type CheckRespExtraType => typeof(TCheckResp); public Type PayReqExtraType => typeof(TPayReq); public Type PayRespExtraType => typeof(TPayResp); public Type PayStatusReqExtraType => typeof(TPayStatusReq); public Type PayStatusRespExtraType => typeof(TPayStatusResp); }
3. 重构服务基类
把原来的6个泛型参数换成一个IServiceParams泛型参数,同时封装带额外参数的请求/响应包装类,让接口逻辑更清晰:
public abstract class BasePaymentController<TParams> : ControllerBase where TParams : IServiceParams, new() { [HttpPost("check")] public async Task<IActionResult> Check([FromBody] BaseServiceRequest<TParams.CheckReqExtraType> request) { var result = await DoCheckAsync(request, request.ExtraInfo); return Ok(new BaseServiceResponse<TParams.CheckRespExtraType> { Success = result.Success, ErrorCode = result.ErrorCode, ErrorMessage = result.ErrorMessage, ExtraInfo = result.ExtraData }); } [HttpPost("pay")] public async Task<IActionResult> Pay([FromBody] BaseServiceRequest<TParams.PayReqExtraType> request) { var result = await DoPayAsync(request, request.ExtraInfo); return Ok(new BaseServiceResponse<TParams.PayRespExtraType> { Success = result.Success, ErrorCode = result.ErrorCode, ErrorMessage = result.ErrorMessage, ExtraInfo = result.ExtraData }); } [HttpPost("pay-status")] public async Task<IActionResult> PayStatus([FromBody] BaseServiceRequest<TParams.PayStatusReqExtraType> request) { var result = await DoPayStatusAsync(request, request.ExtraInfo); return Ok(new BaseServiceResponse<TParams.PayStatusRespExtraType> { Success = result.Success, ErrorCode = result.ErrorCode, ErrorMessage = result.ErrorMessage, ExtraInfo = result.ExtraData }); } // 子类需要实现的具体业务方法 protected abstract Task<CheckResult<TParams.CheckRespExtraType>> DoCheckAsync(BaseServiceRequest baseReq, TParams.CheckReqExtraType extraReq); protected abstract Task<PayResult<TParams.PayRespExtraType>> DoPayAsync(BaseServiceRequest baseReq, TParams.PayReqExtraType extraReq); protected abstract Task<PayStatusResult<TParams.PayStatusRespExtraType>> DoPayStatusAsync(BaseServiceRequest baseReq, TParams.PayStatusReqExtraType extraReq); } // 带额外参数的请求包装类 public class BaseServiceRequest<TExtra> : BaseServiceRequest { public TExtra ExtraInfo { get; set; } } // 带额外参数的响应包装类 public class BaseServiceResponse<TExtra> : BaseServiceResponse { public TExtra ExtraInfo { get; set; } } // 各操作的业务结果模型 public class CheckResult<TRespExtra> { public bool Success { get; set; } public string ErrorCode { get; set; } public string ErrorMessage { get; set; } public TRespExtra ExtraData { get; set; } } public class PayResult<TRespExtra> { public bool Success { get; set; } public string ErrorCode { get; set; } public string ErrorMessage { get; set; } public string TradeNo { get; set; } public TRespExtra ExtraData { get; set; } } public class PayStatusResult<TRespExtra> { public bool Success { get; set; } public string ErrorCode { get; set; } public string ErrorMessage { get; set; } public string TradeStatus { get; set; } public TRespExtra ExtraData { get; set; } }
4. 子类快速实现示例
子类只需要定义好自己的额外参数类,再传入聚合参数类就能快速搭建具体服务:
// 支付宝专属的额外参数类 public class AliPayCheckReqExtra { /* 比如支付宝的AppId、商品编码等 */ } public class AliPayCheckRespExtra { /* 比如支付宝的验签结果、权限信息等 */ } public class AliPayPayReqExtra { /* 比如支付宝的订单金额、支付方式等 */ } public class AliPayPayRespExtra { /* 比如支付宝的支付凭证、回调地址等 */ } public class AliPayPayStatusReqExtra { /* 比如支付宝的交易号、查询类型等 */ } public class AliPayPayStatusRespExtra { /* 比如支付宝的交易详情、退款状态等 */ } // 聚合支付宝所有参数的类 public class AliPayParams : ServiceParams<AliPayCheckReqExtra, AliPayCheckRespExtra, AliPayPayReqExtra, AliPayPayRespExtra, AliPayPayStatusReqExtra, AliPayPayStatusRespExtra> { } // 支付宝具体控制器 public class AliPayController : BasePaymentController<AliPayParams> { protected override async Task<CheckResult<AliPayCheckRespExtra>> DoCheckAsync(BaseServiceRequest baseReq, AliPayCheckReqExtra extraReq) { // 写支付宝校验逻辑 return new CheckResult<AliPayCheckRespExtra> { Success = true, ExtraData = new AliPayCheckRespExtra() }; } protected override async Task<PayResult<AliPayPayRespExtra>> DoPayAsync(BaseServiceRequest baseReq, AliPayPayReqExtra extraReq) { // 写支付宝支付逻辑 return new PayResult<AliPayPayRespExtra> { Success = true, TradeNo = "ALIPAY123456", ExtraData = new AliPayPayRespExtra() }; } protected override async Task<PayStatusResult<AliPayPayStatusRespExtra>> DoPayStatusAsync(BaseServiceRequest baseReq, AliPayPayStatusReqExtra extraReq) { // 写支付宝查询支付状态逻辑 return new PayStatusResult<AliPayPayStatusRespExtra> { Success = true, TradeStatus = "SUCCESS", ExtraData = new AliPayPayStatusRespExtra() }; } }
备选简化方案:直接用泛型接口约束
如果觉得通过Type获取类型不够直观,也可以直接用泛型接口来声明所有参数类型,虽然还是6个泛型参数,但通过接口把它们绑定在一起,可读性比直接写6个泛型参数好很多:
public interface IServiceParams<TCheckReq, TCheckResp, TPayReq, TPayResp, TPayStatusReq, TPayStatusResp> where TCheckReq : class where TCheckResp : class where TPayReq : class where TPayResp : class where TPayStatusReq : class where TPayStatusResp : class { } // 基类直接使用这个泛型接口作为约束 public abstract class BasePaymentController<TParams, TCheckReq, TCheckResp, TPayReq, TPayResp, TPayStatusReq, TPayStatusResp> : ControllerBase where TParams : IServiceParams<TCheckReq, TCheckResp, TPayReq, TPayResp, TPayStatusReq, TPayStatusResp>, new() where TCheckReq : class where TCheckResp : class where TPayReq : class where TPayResp : class where TPayStatusReq : class where TPayStatusResp : class { // 实现逻辑和之前类似,只是泛型参数可以直接使用,不需要通过Type转换 }
内容的提问来源于stack exchange,提问作者SourCreamKun
相关产品推荐
相关产品推荐

