3 回答

TA貢獻1810條經驗 獲得超4個贊
不,你不能。因為屬性名稱已經是一個魔法字符串,并且對于所有意圖和目的,控制器方法的名稱本身就是一個魔法字符串(在您使用隱式操作名稱的情況下)。魔術弦并不壞,只是經常被誤用。在這種情況下,您最好只使用常量。
internal const string ContactActionName2 = nameof(ContactActionName2);
和
[ActionName(ContactActionName2)]
和
HomeController.ContactActionName2
應該足以滿足您的用例。
但是,由于每個人都對此大發雷霆,我決定去尋找一個完全不依賴字符串的解決方案(除了您無法避免依賴的字符串 - 操作名稱)。我不喜歡這個解決方案,因為 1) 它太過分了,2) 它仍然只是訪問一個字符串值,這可以更簡單地使用一個常量來完成,3) 你實際上必須寫出整個方法調用作為一個表達式,并且4) 每次使用時它都會分配一個表達式。
public static class ActionNameExtensions<TController>
{
public static string FindActionName<T>(Expression<Func<TController, T>> expression)
{
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
if (outermostExpression == null)
{
throw new ArgumentException("Not a " + nameof(MethodCallExpression));
}
return outermostExpression.Method.GetCustomAttribute<ActionNameAttribute>().Name;
}
}
用法示例:
public class HomeController : Controller
{
[ActionName("HelloWorld")]
public string MyCoolAction(string arg1, string arg2, int arg4)
{
return ActionNameExtensions<HomeController>.FindActionName(
controller => controller.MyCoolAction("a", "b", 3)
);
}
}
可以編寫一個重載來接受沒有void返回的方法。雖然這有點奇怪,因為它假設用于控制器方法,通常返回一個值。

TA貢獻1993條經驗 獲得超6個贊
...如果操作方法使用 [ActionName] 屬性,有沒有辦法獲得正確的操作名稱(并避免使用魔法字符串)?也許通過 nameof() 和擴展方法的組合?
您可以使用反射。這是一個內聯版本:
<p>@(
(
(ActionNameAttribute)(
typeof(HomeController)
.GetMethod(nameof(HomeController.Contact))
.GetCustomAttributes(typeof(ActionNameAttribute), false)[0]
)
).Name
)</p>
這是與剃刀功能相同的操作:
@functions {
public string GetActionName(Type controller, string methodName) {
var method = controller.GetMethod(methodName);
var attributeType = typeof(ActionNameAttribute);
var attribute = method.GetCustomAttributes(attributeType, false)[0];
return (attribute as ActionNameAttribute).Name;
}
}
<p>@GetActionName(typeof(HomeController), nameof(HomeController.Contact))</p>
這是與通用剃刀函數相同的操作:
@functions {
public string GetActionName<T>(string methodName) {
var controllerType = typeof(T);
var method = controllerType.GetMethod(methodName);
var attributeType = typeof(ActionNameAttribute);
var attribute = method.GetCustomAttributes(attributeType, false)[0];
return (attribute as ActionNameAttribute).Name;
}
}
<p>@(GetActionName<HomeController>(nameof(HomeController.Contact)))</p>
剩下的就是向函數添加防御性編程(例如null檢查)GetActionName。
您的問題專門詢問了擴展方法。據我所知,擴展方法不會提供太大的改進,因為我們正在使用類型和方法,而擴展方法適用于對象。

TA貢獻1815條經驗 獲得超6個贊
如果你不喜歡你可以用泛型做一些非常奇特的邏輯:
public static class HtmlHelperExtensions
{
public static IHtmlContent ActionLink<TController>(
this IHtmlHelper htmlHelper,
string linkText,
string actionName)
where TController : ControllerBase
{
var suffix = nameof(Controller);
var controllerName = typeof(TController).Name.Replace(suffix, "");
var method = typeof(TController).GetMethod(actionName);
var attributeType = typeof(ActionNameAttribute);
var attribute = method.GetCustomAttributes(attributeType, false);
actionName = attribute.Length == 0
? actionName
: (attribute[0] as ActionNameAttribute).Name;
return htmlHelper.ActionLink(linkText, actionName);
}
}
對此進行了測試,它可能會抱怨(很確定會)簽名已經存在,因此您可能必須重命名該方法。在任何情況下,您都可以像這樣使用它:
@(Html.ActionLink<HomeController>("Link Text", nameof(HomeController.Index)))
- 3 回答
- 0 關注
- 404 瀏覽
添加回答
舉報