c#函数作为参数-重复方法结构
本文关键字:方法 结构 -重 参数 函数 | 更新日期: 2023-09-27 18:04:54
我有多个具有不同签名的方法,每个方法都有一个带有自定义日志异常的try-catch块。(多个控制器结构相同).
public class TestController : BaseController
{
public static ActionResult One(int param1, string param2)
{
try
{
// Do something
}
catch (Exception e)
{
LogException(e.Message);
AddModelError(e.Message);
}
return View("ViwName1");
}
public static ActionResult Two(Date param3, bool param4)
{
try
{
// Do something
}
catch (Exception e)
{
LogException(e.Message);
AddModelError(e.Message);
}
return View("ViwName2");
}
}
我想知道是否有一种方法可以避免每个方法的try-catch阻塞,并执行另一个
public class TestController : BaseController
{
public static ActionResult One(int param1, string param2)
{
// Do something (*)
// Call "ActionWithTryCatch" method that has a "function argument" to "Do something (*)"
}
public ActionResult ActionWithTryCatch(MyDelegate del, string viewName)
{
try
{
return del.Invoke();
}
catch (Exception e)
{
LogException(e.Message);
AddModelError(e.Message);
}
return View(viewName);
}
}
我该怎么做呢?我见过使用委托的例子,但我知道那是强类型的,所以没有找到这样做的方法。谢谢!
您所描述的模式接近于面向方面编程(AOP)的一种形式。然而,如果你只是想将特定的Try Catch错误处理逻辑应用到控制器上的所有操作,那么可能不值得你引入整个AOP框架。相反,您可以利用HandleErrorAttribute
或覆盖控制器类的OnException
方法。
例如,你可以这样写你的控制器:
public class TestController
{
private TestService service;
public TestController(TestService service)
{
this.service = service;
}
public ActionResult One(int param1, string param2)
{
this.service.MethodOne(param1, param2);
return View("ViwName1");
}
public ActionResult Two(Date param3, bool param4)
{
this.service.MethodTwo(param3, param4);
return View("ViwName2");
}
protected override void OnException(ExceptionContext filterContext)
{
LogException(filterContext.Exception.Message);
AddModelError(filterContext.Exception.Message);
var errorView = new ViewResult { ViewName = "~/Path/To/Error/View" };
filterContext.Result = errorView;
}
}
如果你想把它抽象出来,那么你可以把覆盖的OnException逻辑移到一个基控制器类中,然后让你所有的控制器都继承自基控制器。
如果你想看到MVC中统一错误处理的其他方法,那么也可以查看这个博客:https://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging
根据我的评论,如果你坚持实现你所描述的模式,你可以使用gilmishal的答案的修改版本。
public class TestController
{
private TestService service;
public TestController(TestService service)
{
this.service = service;
}
public ActionResult One(int param1, string param2)
{
return this.ActionWithTryCatch(() => this.service.MethodOne(param1, param2), "ViwName1");
}
public ActionResult Two(Date param3, bool param4)
{
return this.ActionWithTryCatch(() => this.service.MethodTwo(param3, param4), "ViwName2");
}
public IActionResult ActionWithTryCatch(Action action, string viewName)
{
try
{
action.Invoke();
}
catch (Exception e)
{
LogException(e.Message);
AddModelError(e.Message);
}
return View(viewName);
}
}
如果你需要在js中传递参数给这个函数,你创建的这个方法将不能正常工作-所以我假设你只调用无参数的方法。
在这种情况下,你可以用Func<IActionResult>
代替MyDelegate
。
public TResult ActionWithTryCatch<TResult>(Func<TResult> del, string viewName)
{
try
{
return del.Invoke();
}
catch (Exception e)
{
LogException(e.Message);
AddModelError(e.Message);
throw;
}
}
这将更类似于您的javascript实现,并将在unhandledexception时返回500 HTTP结果。
你应该这样调用它,如果你想要IActionResult
返回类型-
ActionWithTryCatch<IActionResult>(MethodThatReturnsIActionResult, viewName);
我建议您查看泛型