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

如何将C#字符串关键字映射到Mediator命令或查询?

优雅替代大量if-else的MediatR动作映射方案

方案1:字典映射(策略模式简化版)

直接用字典建立action字符串到执行委托的映射,启动时一次性注册所有规则,运行时直接通过key匹配执行,性能高且易维护。

示例代码:

// 定义字典,可注入为单例服务
private readonly Dictionary<string, Func<IMediator, Task<object>>> _actionMappings;

// 初始化映射(比如在构造函数或Startup中)
public YourApiController(IMediator mediator)
{
    _actionMappings = new Dictionary<string, Func<IMediator, Task<object>>>
    {
        ["GetAllOrders"] = async (mediator) => await mediator.Send(new GetAllOrdersQuery()),
        ["GetAllProducts"] = async (mediator) => await mediator.Send(new GetAllProductsQuery()),
        ["GetAllCustomers"] = async (mediator) => await mediator.Send(new GetAllCustomersQuery())
    };
}

// API动作方法
[HttpPost]
public async Task<IActionResult> HandleAction([FromBody] dynamic payload)
{
    string action = payload.action.ToString();
    if (_actionMappings.TryGetValue(action, out var execute))
    {
        var result = await execute(_mediator);
        return Ok(result);
    }
    return BadRequest($"Unsupported action: {action}");
}

优点:执行效率高,逻辑直观,调试方便;缺点:新增动作时需要手动更新字典。


方案2:特性标记+反射扫描

给每个MediatR请求类添加自定义特性,标记对应的action名称,启动时自动扫描所有请求类型并建立映射,减少手动维护成本。

第一步,定义自定义特性:

[AttributeUsage(AttributeTargets.Class)]
public class ActionMappingAttribute : Attribute
{
    public string ActionName { get; }
    public ActionMappingAttribute(string actionName)
    {
        ActionName = actionName;
    }
}

第二步,给请求类标记特性:

[ActionMapping("GetAllOrders")]
public class GetAllOrdersQuery : IRequest<object> { }

[ActionMapping("GetAllProducts")]
public class GetAllProductsQuery : IRequest<object> { }

第三步,启动时扫描并构建映射:

// 扫描程序集中所有带ActionMappingAttribute的MediatR请求类型
var requestTypes = Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => typeof(IRequest<object>).IsAssignableFrom(t) && t.GetCustomAttribute<ActionMappingAttribute>() != null);

// 构建映射字典
_actionMappings = new Dictionary<string, Type>();
foreach (var type in requestTypes)
{
    var attr = type.GetCustomAttribute<ActionMappingAttribute>();
    _actionMappings[attr.ActionName] = type;
}

第四步,API方法中执行:

[HttpPost]
public async Task<IActionResult> HandleAction([FromBody] dynamic payload)
{
    string action = payload.action.ToString();
    if (_actionMappings.TryGetValue(action, out var requestType))
    {
        // 创建请求实例(如需传递参数,可从payload中反序列化)
        var request = Activator.CreateInstance(requestType);
        var result = await _mediator.Send(request as IRequest<object>);
        return Ok(result);
    }
    return BadRequest($"Unsupported action: {action}");
}

优点:新增请求类只需加特性,无需手动更新映射;缺点:启动时反射扫描有轻微性能开销,复杂参数传递需要额外处理反序列化。


方案3:基于类名的直接映射(简化版反射)

如果action字符串和请求类名完全匹配(比如"GetAllOrders"对应GetAllOrdersQuery或GetAllOrdersCommand),可以直接通过类名拼接反射创建实例,无需额外特性或字典注册。

示例代码:

[HttpPost]
public async Task<IActionResult> HandleAction([FromBody] dynamic payload)
{
    string action = payload.action.ToString();
    // 假设请求类命名规则是{Action}Query或{Action}Command,先尝试Query
    var requestTypeName = $"YourNamespace.{action}Query";
    var requestType = Type.GetType(requestTypeName);
    
    if (requestType == null)
    {
        // 尝试Command
        requestTypeName = $"YourNamespace.{action}Command";
        requestType = Type.GetType(requestTypeName);
    }

    if (requestType != null && typeof(IRequest<object>).IsAssignableFrom(requestType))
    {
        var request = Activator.CreateInstance(requestType);
        var result = await _mediator.Send(request as IRequest<object>);
        return Ok(result);
    }
    return BadRequest($"Unsupported action: {action}");
}

优点:完全无需手动维护映射,零配置;缺点:对类名命名规则要求严格,灵活性差,参数传递同样需要额外反序列化处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:55:28