是否可以将代码提取到委托中?

Is it possible to extract code into delegate?

更新: 我遇到的问题是模型验证,但我发现当模型传递给 Action 时 FluentValidation 已经解决了这个问题,所以我的问题并不完全正确并且可能具有误导性。我会关闭它(如果找到如何操作)。

我有以下代码:

        [HttpPost]
    public async Task<IActionResult> Create(CreateAccountViewModel model)
    {
        try
        {
            **await Mediator.Send(_mapper.Map<CreateAccountCommand>(model));
            return RedirectToAction("Index");**
        }
        catch (ValidationException vldEx)
        {
            foreach (var vldError in vldEx.Errors)
            {
                ModelState.AddModelError(vldError.PropertyName, vldError.ErrorMessage);
            }

            return View(model);
        }
    }

try里面的文字随着controller的不同动作不同而不同,其他都是一样的。是否可以将公共代码提取到基class中的函数中? 我尝试使用 Func,但无法找到正确的方法。 我正在寻找这样的东西:

        [HttpPost]
    public async Task<IActionResult> Create(CreateAccountViewModel model)
    {
        FunctionWithCommonCode(x =>
        {
            await Mediator.Send(_mapper.Map<CreateAccountCommand>(model));
            return RedirectToAction("Index");
        });
    }

不需要委托或任何复杂的东西,只需创建一个您从每个操作调用的基本方法并传入您需要的字符串,例如:

private async Task<IActionResult> CreateBase(CreateAccountViewModel model, string action)
{
    try
    {
        await Mediator.Send(_mapper.Map<CreateAccountCommand>(model));
        return RedirectToAction(action);
    }
    catch (ValidationException vldEx)
    {
        foreach (var vldError in vldEx.Errors)
        {
            ModelState.AddModelError(vldError.PropertyName, vldError.ErrorMessage);
        }

        return View(model);
    }
}

操作方法如下所示:

[HttpPost]
public async Task<IActionResult> Create(CreateAccountViewModel model)
{
    return await CreateBase(model, "Index");
}

我无法编译它 - 有太多对您未提供的代码的依赖。如果您可以提供最小的、完整的和可验证的示例 (https://whosebug.com/help/minimal-reproducible-example),并有足够的存根 类 来编译您的示例代码(不依赖于您不提供的代码),那么我会更新我的回答。

但是,如果我理解你的问题,你需要做的是创建一个方法来完成除了你的 **star-ed** 代码之外的所有事情,并将带星号的代码作为参数传递给适当的委托类型。抱歉,但是因为我无法编译,所以我不确定我是否在正确的位置进行了异步和等待。但是,这应该会给您一个良好的开端。

因此,您从提供所有样板的辅助函数开始:

private async Task<IActionResult> WebWorker<TModel> (TModel model, Func<TModel, Task<IActionResult>> workToDo) {
    try {
        return await workToDo(TModel model);
    } catch (ValidationException vldEx) {
        foreach (var vldError in vldEx.Errors) {
            ModelState.AddModelError(vldError.PropertyName, vldError.ErrorMessage);
        }
        return View(model);
    }
}

该函数采用您的模式和适当 Func<> 类型的委托。

然后你可以这样称呼它:

 [HttpPost]
 public async Task<IActionResult> Create(CreateAccountViewModel model) {
     return await WebWorker<CreateAccountViewModel>(model,
          m => {
             Mediator.Send(_mapper.Map<CreateAccountCommand>(m));
             return RedirectToAction("Index");
         });
 }

请注意,WebWorker 函数的第二个参数是一个 Lambda,其签名与声明为该函数第二个参数的 Func 的签名匹配。