【发布时间】:2023-03-30 17:55:02
【问题描述】:
我已经阅读了多个类似的帖子和博客
Delegate-based strongly-typed URL generation in ASP.NET MVC
但他们都没有真正做到我想做的事。目前我有一种混合方法,例如:
// shortened for Brevity
public static Exts
{
public string Action(this UrlHelper url,
Expression<Func<T, ActionResult>> expression)
where T : ControllerBase
{
return Exts.Action(url, expression, null);
}
public string Action(this UrlHelper url,
Expression<Func<T, ActionResult>> expression,
object routeValues)
where T : ControllerBase
{
string controller;
string action;
// extension method
expression.GetControllerAndAction(out controller, out action);
var result = url.Action(action, controller, routeValues);
return result;
}
}
如果您的控制器方法没有任何参数,则效果很好:
public class MyController : Controller
{
public ActionResult MyMethod()
{
return null;
}
public ActionResult MyMethod2(int id)
{
return null;
}
}
那么我可以:
Url.Action<MyController>(c => c.MyMethod())
但是如果我的方法需要一个参数,那么我必须传递一个值(我永远不会使用):
Url.Action<MyController>(c => c.MyMethod2(-1), new { id = 99 })
所以问题是有没有办法改变扩展方法,仍然要求第一个参数是在类型 T 上定义的方法,确实检查以确保返回参数是 @ 987654327@ 没有实际指定参数,例如:
Url.Action<MyController>(c => c.MyMethod2, new { id = 99 })
所以这将传递一个指向方法的指针(就像一个反射MethodInfo)而不是Func<>,所以它不会关心参数。如果可能,该签名会是什么样子?
【问题讨论】:
-
使用
c.MyMethod2,您指向的是一个方法group,其中任何一个都可以返回其他内容...但我很确定我已经看到了这样的库启用此功能。也许您可以做一些反射魔术并检查GetControllerAndAction与提供的参数匹配的组的方法确实返回ActionResult。这不会完全为您提供您正在寻找的编译时安全性,但无论如何您都不应该在控制器中将非操作方法作为公共方法。 -
c => c.MyMethod2不能从Method Group转换为非委托类型ActionResult。 -
您当然是对的,这仅适用于当前控制器,而不适用于视图。你为什么不使用
c => c.MyMethod2(99)代替(使用MethodCallExpression.Arguments来获取参数)? -
让我考虑一下...我故意删除了该代码,因为它看起来模棱两可:
c => c.MyMethod(99), new { id = 98 }...但也许我那时不需要路由值...我是试图想出一个我需要路由值的原因......
标签: c# asp.net-mvc expression func