2

有人对我如何从 T4 模板中的 MVC 应用程序中提取路由表有任何想法吗?

理想情况下,我想做的是创建一个'MvcApplication:System.Web.HttpApplication'的实例并将其设置为'startup',这样路由就被注册了,我可以从Routes.RouteTable中提取它们。

如果做不到这一点,我考虑使用反射来查找具有遵循 Register[xxxx]Route 命名约定的方法的静态类。在很多情况下都可以工作。

我可能错过的任何其他建议?

编辑 - 似乎对这个问题有些困惑。我知道 T4 在设计时运行。我知道路由是在运行时注册的。这个做了一些类似于我想做的事情——在设计时提取 roues,但他强迫你以一种特定的方式注册路由,这样他就可以使用反射来读回它们。如果可能的话,想避免这种情况。

4

1 回答 1

1

您可以在具有方法的 MVC 期货中使用库 Microsoft.Web.Mvc

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

它给你你想要的。

更新:它可以在没有 Asp.Net MVC 的情况下工作,但您需要将 Microsoft.Web.Mvc.Internal.ExpressionHelper 的实现复制到您自己的类中,并where TController:Controller从 GetRouteValuesFromExpression 方法的签名中删除限制:

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);
        }
    }
}
于 2012-09-01T18:20:44.203 回答