2012-09-01 44 views
2

有沒有人有任何想法可以從T4模板中的MVC應用中提取路由表?在T4模板中從MVC應用中提取路由表

理想情況下,Id喜歡做的是創建一個'MvcApplication:System.Web.HttpApplication'的實例並將其啓動到'startup',這樣路由就被註冊了,我可以從Routes.RouteTable中提取它們。

失敗了,我想過使用反射來查找靜態類,方法遵循Register [xxxx] Route命名約定。會在很多情況下工作。

我可能錯過了其他建議嗎?

編輯 - 似乎對這個問題有些困惑。我知道T4在設計時運行。我知道路由是在運行時註冊的。這guy做了類似於即將做的事情 - 在設計時提取roues,但他強迫你以特定的方式註冊路由,以便他可以使用反射將其讀出。希望儘可能避免這種情況。

+0

你想得到什麼目的? –

+0

我想嘗試自動生成路由中的強類型幫助器 - 這些基本上都是圍繞UrlHelper.RouteUrl的包裝器方法。我知道我可以使用TVMC和ActionLink作爲替代方案。 –

+0

但是... HttpApplication實例註冊路由...您希望誰填寫路由表,您希望閱讀哪些表?你需要一些其他配置路由的方式,以便你的T4能夠讀取它們。 T4是設計時而不是運行時執行。 –

回答

1

您可以使用MVC期貨庫Microsoft.Web.Mvc有方法

ExpressionHelper.GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) 

它給你想要的東西。

更新:它可以在不Asp.Net MVC的工作,但你需要實現Microsoft.Web.Mvc.Internal.ExpressionHelper複製到自己的類和方法GetRouteValuesFromExpression簽名刪除限制where TController:Controller

public static class MyOwnExpressionHelper 
{ 
    public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) //where TController : Controller 
    { 
     if (action == null) 
      throw new ArgumentNullException("action"); 
     MethodCallExpression call = action.Body as MethodCallExpression; 
     if (call == null) 
      throw new ArgumentException("MustBeMethodCall", "action"); 
     string name = typeof(TController).Name; 
     if (!name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) 
      throw new ArgumentException("TargetMustEndInController", "action"); 
     string str = name.Substring(0, name.Length - "Controller".Length); 
     if (str.Length == 0) 
      throw new ArgumentException("_CannotRouteToController", "action"); 
     string targetActionName = GetTargetActionName(call.Method); 
     RouteValueDictionary rvd = new RouteValueDictionary(); 
     rvd.Add("Controller", (object)str); 
     rvd.Add("Action", (object)targetActionName); 
     ActionLinkAreaAttribute linkAreaAttribute = Enumerable.FirstOrDefault<object>((IEnumerable<object>)typeof(TController).GetCustomAttributes(typeof(ActionLinkAreaAttribute), true)) as ActionLinkAreaAttribute; 
     if (linkAreaAttribute != null) 
     { 
      string area = linkAreaAttribute.Area; 
      rvd.Add("Area", (object)area); 
     } 
     AddParameterValuesFromExpressionToDictionary(rvd, call); 
     return rvd; 
    } 

    public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression) 
    { 
     if (expression.Body.NodeType == ExpressionType.Call) 
      return GetInputName((MethodCallExpression)expression.Body).Substring(expression.Parameters[0].Name.Length + 1); 
     else 
      return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1); 
    } 

    private static string GetInputName(MethodCallExpression expression) 
    { 
     MethodCallExpression expression1 = expression.Object as MethodCallExpression; 
     if (expression1 != null) 
      return MyOwnExpressionHelper.GetInputName(expression1); 
     else 
      return expression.Object.ToString(); 
    } 

    private static string GetTargetActionName(MethodInfo methodInfo) 
    { 
     string name = methodInfo.Name; 
     if (methodInfo.IsDefined(typeof(NonActionAttribute), true)) 
     { 
      throw new InvalidOperationException(string.Format((IFormatProvider)CultureInfo.CurrentCulture,"An Error", new object[1] 
    { 
     (object) name 
    })); 
     } 
     else 
     { 
      ActionNameAttribute actionNameAttribute = Enumerable.FirstOrDefault<ActionNameAttribute>(Enumerable.OfType<ActionNameAttribute>((IEnumerable)methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true))); 
      if (actionNameAttribute != null) 
       return actionNameAttribute.Name; 
      if (methodInfo.DeclaringType.IsSubclassOf(typeof(AsyncController))) 
      { 
       if (name.EndsWith("Async", StringComparison.OrdinalIgnoreCase)) 
        return name.Substring(0, name.Length - "Async".Length); 
       if (name.EndsWith("Completed", StringComparison.OrdinalIgnoreCase)) 
        throw new InvalidOperationException(string.Format((IFormatProvider)CultureInfo.CurrentCulture, "CannotCallCompletedMethod", new object[1] 
     { 
      (object) name 
     })); 
      } 
      return name; 
     } 
    } 

    private static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call) 
    { 
     ParameterInfo[] parameters = call.Method.GetParameters(); 
     if (parameters.Length <= 0) 
      return; 
     for (int index = 0; index < parameters.Length; ++index) 
     { 
      Expression expression = call.Arguments[index]; 
      ConstantExpression constantExpression = expression as ConstantExpression; 
      object obj = constantExpression == null ? CachedExpressionCompiler.Evaluate(expression) : constantExpression.Value; 
      rvd.Add(parameters[index].Name, obj); 
     } 
    } 
} 
+0

所以這將工作從T4模板?即不是正在運行的MVC應用程序的一部分。我自己試試,但我不在我的電腦前。 –

+0

你的應用程序是一個asp.net應用程序嗎? –

+0

我更新了我的答案 –