urlhelper.Action无需硬编码字符串用于控制和控制功能



我想创建一个方便的助手方法,该方法有助于从给定控制器类型和该控制器上的操作/方法构造URL。在ASP.NET Core MVC中,有一个IUrlHelper.Action(string actionName, string controllerName)方法可以执行相同的操作。

但是,而不是这样: UrlHelper.Action("MyAction", "MyController")

我想使用:UrlHelper.Action<MyController>(c => c.MyAction)

现在,我仅部分设法解决了这个问题,这使我可以使用以下代码来执行类似的事情: UrlHelper.Action<MyController>(c => c.MyAction())(请注意操作名称之后的括号(:

    public static string ActionFor<TController>(this IUrlHelper source, Expression<Func<TController, object>> memberExpression) where TController : Controller
    {
        if (!(memberExpression.Body is MemberExpression body)) throw new ArgumentException($"Expression must be a {typeof(MemberExpression).Name}.", nameof(memberExpression));
        return source.Action(body.Member.Name, typeof(TController).RemoveControllerSufix());
    }

,但我不知道如何告诉编译器我希望memberExpression参数接受方法组(或类似(,因此我可以编写无括号的动作名称。

P.S。我们还可以做类似:UrlHelper.Action<MyController>(nameof(MyController.MyAction))的事情,它也避免了字符串的硬编码,但仍然复制控制器类型,这也很棒。

我想我在某处看到了乔恩·斯基特(Jon Skeet(的帖子,与类似的东西有关,但我现在找不到它...

获取方法组的名称有点麻烦。这就是它的工作原理(在dotnet6/c#10.0中进行了测试(。

致电获取方法组的名称:

var name = GetMethodGroupName<Foo>(f => f.Bar);
// name: "Bar"

模式匹配的方法

private static string GetMethodGroupName<TController>(Expression<Func<TController, object>> memberExpression)
{
    if (memberExpression.Body is UnaryExpression
        { Operand: MethodCallExpression
            { Object: ConstantExpression
                { Value: MethodInfo me } } })
        return me.Name;
    throw new ArgumentException(
        "expression does not look like a method group.", 
        nameof(memberExpression));
}

...或与con缩的检查...

private static string GetMethodGroupName<TController>(Expression<Func<TController, object>> memberExpression)
{
    if (memberExpression.Body is UnaryExpression ue)
        if (ue.Operand is  MethodCallExpression mce)
            if (mce.Object is ConstantExpression ce)
                if (ce.Value is MethodInfo me)
                    return me.Name;
    throw new ArgumentException(
        "expression does not look like a method group.", 
        nameof(memberExpression));
}

最新更新