0

随着我进一步构建我的 ASP.Net MVC 网站,我遇到了一些我想重构为更灵活的硬编码。

在我看来,我一直在传递一个如下所示的 MenuItemModel:

public class MenuItemModel {
    public MenuItemModel(string aLinkName, string aArea
                              , string aController, string aAction) {

    public string LinkName { get; private set; }
    public string Area { get; private set; }
    public string Controller { get; private set; }
    public string Action { get; private set; }

    public bool isActive { get; set; }
}

所以在视图中,我可以创建一个链接:

@Html.ActionLink( @Model.LinkName , @Model.Action 
            , @Model.Controller , new { Area = @Model.Area } , new { } )

这意味着我必须像这样创建一堆 MenuItemModel:

MenuItemModel MIM=new MenuItemModel("History","Transactions","History","Index");

这很好用,它创建了正确的链接。

但是我看到未来会出现一个大问题.. 这种策略对 Resharper 的重构能力没有弹性。当我们添加新功能时,我希望将来能够重新定义我的区域名称、控制器名称甚至动作名称。通过硬编码区域名称的文字“Transactions”,我现在必须手动重构整个网站以找到所有“Transactions”文字并在我们更改区域名称时将它们替换为其他内容;或将一个区域分成更小的区域,等等。呸。

如果我要实例化到 ActionResult 的链接,有没有办法从中获取控制器名称、区域和操作名称?那里有我不知道的助手吗?

一种方法是使用:

myController.GetType()

并检查类型属性并从类型中的“全名”中解析出区域和控制器名称,但我没有这种方法……它返回 ActionResult 的类型信息并且没有识别名称。

想法?

4

2 回答 2

0

您可以使用T4 MVC 模板生成强类型帮助器来消除文字。它们当然有助于重构,尽管使用起来可能有点麻烦(并且会给你的 resharper 类型的搜索增加噪音)。

于 2013-11-07T17:53:02.777 回答
0

我能想到的方法有两种:

  1. 假设您使用的是 C# 版本 6 或更高版本,则使用nameof 关键字。
  2. 使用 lambda 表达式

使用名称

回到您的代码,我认为您可以将 nameof 与以下内容一起使用:

var controllerName = typeof(HistoryController).Name;
var mvcNameOfController = 
    controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
var actionName = nameof(History.Index);

var menuItemModel = 
    new MenuItemModel("History","Transactions", mvcNameOfController, actionName);

使用 lambda 表达式

使用 lambda 表达式,您可以执行以下操作:

public static MenuItemModel GetMenuItemFor<TController>(
    string aLinkName, string aArea, 
    Expression<Action<TController>> expression
) where T : Controller
{
    var controllerName = typeof(T).Name;
    var mvcNameOfController = 
        controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
    var methodName = ((MethodCallExpression)expression.Body).Method.Name;
    return new MenuItemModel(aLinkName, aArea, mvcNameOfController, methodName);
}

您可以像这样使用它:

var menuItemModel = 
    GetMenuItemFor<HistoryController>("History", "Transactions", x => x.Index());
于 2016-03-22T21:36:29.193 回答