解读ASP.NET 5 & MVC6系列教程(12):基于Lamda表达式的强类型R
| 前面的深入理解Routing章节,我们讲到了在MVC中,除了使用默认的ASP.NET 5的路由注册方式,还可以使用基于Attribute的特性(Route和HttpXXX系列方法)来定义。本章,我们将讲述一种基于Lambda表达式的强类型类型。 这种方式的基本使用示例如下: 
services.Configure<MvcOptions>(opt =>
{
 opt.EnableTypedRouting();
 opt.GetRoute("homepage", c => c.Action<ProductsController>(x => x.Index()));
 opt.GetRoute("aboutpage/{name}", c => c.Action<ProductsController>(x => x.About(Param<string>.Any)));
 opt.PostRoute("sendcontact", c => c.Action<ProductsController>(x => x.Contact()));
});从示例中可以看出,我们可以通过GetRoute或PostRoute等扩展方法来定义route,而且后面使用Lambda表达式来定Controller的类型和Action的方法。 注意,在这里获取Action的方法名,是通过委托执行该Action方法来实现的(实际上并没有执行,而是基于此获取该Action的MethodInfo)。 实现原理 在 
public interface IApplicationModelConvention
{
 void Apply(ApplicationModel application);
}接口中的 
public class ApplicationModel
{
 public ApplicationModel();
 public IList<ControllerModel> Controllers { get; }
 public IList<IFilter> Filters { get; }
}这里最重要的就是 新的IApplicationModelConvention注册方式如下: 
services.Configure<MvcOptions>(opt =>
{
 opts.ApplicationModelConventions.Add(new MyApplicationModelConvention());
});所以我们可以利用这个方法,在合适的时机对整个MVC的程序模型做响应的调整和修改,本章节中的强类型路由就是利用这个特性来实现的。 实现步骤 首先定义一个强类型的路由模型 
public class TypedRouteModel : AttributeRouteModel
{
 public TypedRouteModel(string template)
 {
  Template = template;
  HttpMethods = new string[0];
 }
 public TypeInfo ControllerType { get; private set; }
 public MethodInfo ActionMember { get; private set; }
 public IEnumerable<string> HttpMethods { get; private set; }
 public TypedRouteModel Controller<TController>()
 {
  ControllerType = typeof(TController).GetTypeInfo();
  return this;
 }
 public TypedRouteModel Action<T, U>(Expression<Func<T, U>> expression)
 {
  ActionMember = GetMethodInfoInternal(expression);
  ControllerType = ActionMember.DeclaringType.GetTypeInfo();
  return this;
 }
 public TypedRouteModel Action<T>(Expression<Action<T>> expression)
 {
  ActionMember = GetMethodInfoInternal(expression);
  ControllerType = ActionMember.DeclaringType.GetTypeInfo();
  return this;
 }
 private static MethodInfo GetMethodInfoInternal(dynamic expression)
 {
  var method = expression.Body as MethodCallExpression;
  if (method != null)
   return method.Method;
  throw new ArgumentException("Expression is incorrect!");
 }
 public TypedRouteModel WithName(string name)
 {
  Name = name;
  return this;
 }
 public TypedRouteModel ForHttpMethods(params string[] methods)
 {
  HttpMethods = methods;
  return this;
 }
}该类主要的功能是:定义支持传入Controller类型,支持链式调用。 然后再定义一个继承 
public class TypedRoutingApplicationModelConvention : IApplicationModelConvention
{
 internal static readonly Dictionary<TypeInfo, List<TypedRouteModel>> Routes = new Dictionary<TypeInfo, List<TypedRouteModel>>();
 public void Apply(ApplicationModel application)
 {
  foreach (var controller in application.Controllers)
  {
   if (Routes.ContainsKey(controller.ControllerType))
   {
    var typedRoutes = Routes[controller.ControllerType];
    foreach (var route in typedRoutes)
    {
     var action = controller.Actions.FirstOrDefault(x => x.ActionMethod == route.ActionMember);
     if (action != null)
     {
      action.AttributeRouteModel = route;
      //注意这里是直接替换,会影响现有Controller上的Route特性定义的路由
      foreach (var method in route.HttpMethods)
      {
       action.HttpMethods.Add(method);
      }
     }
    }
   }
  }
 }
}(编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! | 

