• Controller的创建


      在ControllerBuilder类中设置ControllerFactory,然后使用ControllerFactory创建Controller。 http请求在进入httphandler映射处理时,通过ControllerBuilder的Current获取ControllerFactory,然后使用默认或者注册的(如果注册地话)ControllerFactory创建controller。默认的工厂是一个DefaultControllerFactory对象,由下面代码可以看出。

    internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
    {
          ControllerBuilder controllerBuilder = this;
          IResolver<IControllerFactory> resolver = serviceResolver;
          if (resolver == null)
            resolver = (IResolver<IControllerFactory>) new SingleServiceResolver<IControllerFactory>((Func<IControllerFactory>) (() => this._factoryThunk()),(IControllerFactory) new DefaultControllerFactory()
            {
              ControllerBuilder = this
            }, "ControllerBuilder.GetControllerFactory");
          controllerBuilder._serviceResolver = resolver;
     }
    

      而Controller的产生是通过DefaultControllerFactoryCreateController来实现的,代码如下:

    public virtual IController CreateController(RequestContext requestContext, string controllerName)
    {
          if (requestContext == null)
            throw new ArgumentNullException("requestContext");
          if (string.IsNullOrEmpty(controllerName))
            throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
          Type controllerType = this.GetControllerType(requestContext, controllerName);
          return this.GetControllerInstance(requestContext, controllerType);
    }
    

      然后查看GetControllerType方法:

    protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName)
    {
          if (string.IsNullOrEmpty(controllerName))
            throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
          object obj;
          if (requestContext != null && requestContext.RouteData.DataTokens.TryGetValue("Namespaces", out obj))
          {
            IEnumerable<string> enumerable = obj as IEnumerable<string>;
            if (enumerable != null && Enumerable.Any<string>(enumerable))
            {
              HashSet<string> namespaces = new HashSet<string>(enumerable, (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
              Type withinNamespaces = this.GetControllerTypeWithinNamespaces(requestContext.RouteData.Route,                      controllerName, namespaces);
              if (withinNamespaces != (Type) null || false.Equals(requestContext.RouteData.DataTokens["UseNamespaceFallback"]))
                return withinNamespaces;
            }
          }
          if (this.ControllerBuilder.DefaultNamespaces.Count > 0)
          {
            HashSet<string> namespaces = new HashSet<string>((IEnumerable<string>) this.ControllerBuilder.DefaultNamespaces,        (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
            Type withinNamespaces = this.GetControllerTypeWithinNamespaces(requestContext.RouteData.Route, controllerName, namespaces);
            if (withinNamespaces != (Type) null)
              return withinNamespaces;
          }
          return this.GetControllerTypeWithinNamespaces(requestContext.RouteData.Route, controllerName, (HashSet<string>) null);
    }
    

      可以看到最终都归结到同一个方法GetControllerTypeWithinNamespaces中,代码如下:

    private Type GetControllerTypeWithinNamespaces(RouteBase route, string controllerName, HashSet<string> namespaces)
    {
          this.ControllerTypeCache.EnsureInitialized(this.BuildManager);
          ICollection<Type> controllerTypes = this.ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
          switch (controllerTypes.Count)
          {
            case 0:
              return (Type) null;
            case 1:
              return Enumerable.First<Type>((IEnumerable<Type>) controllerTypes);
            default:
              throw DefaultControllerFactory.CreateAmbiguousControllerException(route, controllerName, controllerTypes);
          }
     }
    

      而方法EnsureInitialized()是通过IBuildManager获取程序中所有实现了IController的类型,然后在这些类型里用路由数据或者ControllerBuilder中的命名空间和controller的名称进行匹配,如果没有匹配,返回null,如果有一个匹配,返回,如果有多个,抛出异常!

      现在获取到了controllerType的类型,然后返回到工厂的CreateController的最后一步,查看GetControllerInstance方法,代码如下:

    protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
     {
          if (controllerType == (Type) null)
          {
            throw new HttpException(404, string.Format((IFormatProvider) CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_NoControllerFound, new object[1]
            {
              (object) requestContext.HttpContext.Request.Path
            }));
          }
          else
          {
            if (typeof (IController).IsAssignableFrom(controllerType))
              return this.ControllerActivator.Create(requestContext, controllerType);
            throw new ArgumentException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase, new object[1]
            {
              (object) controllerType
            }), "controllerType");
          }
     }
    

      可以看到,这个时候又使用到了另外一个对象ControllerActivator,由DefaultControllerFactory的构造函数可以看出

    internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver)
     {
          if (controllerActivator != null)
            this._controllerActivator = controllerActivator;
          else
            this._activatorResolver = activatorResolver ?? (IResolver<IControllerActivator>) new SingleServiceResolver<IControllerActivator>((Func<IControllerActivator>) (() => (IControllerActivator) null),(IControllerActivator) new DefaultControllerFactory.DefaultControllerActivator(dependencyResolver), "DefaultControllerFactory constructor");
     }
    

    默认使用的是实现了接口IResolver<TService>的SingleServiceResolver<TService>对象默认注册的一个内部对象DefaultControllerActivator,然后调用它的create方法,代码如下:

    public IController Create(RequestContext requestContext, Type controllerType)
     {
            try
            {
              return (IController) (this._resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
            }
            catch (Exception ex)
            {
              throw new InvalidOperationException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_ErrorCreatingController, new object[1]
              {
                (object) controllerType
              }), ex);
            }
     }
    

      而DefaultControllerActivator对象中的属性_resolverThunk是一个Func<IDependencyResolver> _resolverThunk委托对象,我们通过DefaultControllerFactory构造函数中调用的new DefaultControllerFactory.DefaultControllerActivator(dependencyResolver),可以看到DefaultControllerActivator的构造函数

    public DefaultControllerActivator(IDependencyResolver resolver)
    {
            if (resolver == null)
              this._resolverThunk = (Func<IDependencyResolver>) (() => DependencyResolver.Current);
            else
              this._resolverThunk = (Func<IDependencyResolver>) (() => resolver);
    }
    

      对它的设置,如果在自己实现的ControllerFactory的构造函数中传递了自己定义的一个IDependencyResolver对象或者DependencyResolver的SetResolver方法设置了一个自定义的IDependencyResolver对象,就会使用它,如果没有,则使用默认的DependencyResolver.Current,可以看到DependencyResolver.Current是一个实现了IDependencyResolver接口对象的引用,从他的构造函数

    public DependencyResolver()
    {
          this.InnerSetResolver((IDependencyResolver) new DependencyResolver.DefaultDependencyResolver());
    }
    

      看出它使用的是一个内部私有的对象DefaultDependencyResolver

    private class DefaultDependencyResolver : IDependencyResolver
    {
          public object GetService(Type serviceType)
          {
            if (!serviceType.IsInterface)
            {
              if (!serviceType.IsAbstract)
              {
                try
                {
                  return Activator.CreateInstance(serviceType);
                }
                catch
                {
                  return (object) null;
                }
              }
            }
            return (object) null;
          }
    
          public IEnumerable<object> GetServices(Type serviceType)
          {
            return Enumerable.Empty<object>();
          }
     }
    

    它的GetService方法,通过反射创建了我们需要的controller对象,由此,controller创建成功!

    Area中controller的解析过程:

      首先我们知道,在程序刚启动时,我们会调用AreaRegistration.RegisterAllAreas()方法:

     internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
    {
          foreach (Type type in TypeCacheUtil.GetFilteredTypesFromAssemblies("MVC-AreaRegistrationTypeCache.xml",            new Predicate<Type>(AreaRegistration.IsAreaRegistrationType), buildManager))
            ((AreaRegistration) Activator.CreateInstance(type)).CreateContextAndRegister(routes, state);
    }
    

      它是先查找出程序中所有实现了AreaRegistration的区域对象,然后创建他们的实例,调用实例的CreateContextAndRegister方法,来创建AreaRegistrationContext对象,

    internal void CreateContextAndRegister(RouteCollection routes, object state)
    {
          AreaRegistrationContext context = new AreaRegistrationContext(this.AreaName, routes, state);
          string @namespace = this.GetType().Namespace;
          if (@namespace != null)
            context.Namespaces.Add(@namespace + ".*");
          this.RegisterArea(context);
    }
    

      然后调用RegisterArea方法,对路由进行注册,可以看出,这个时候还做了一个额外的事情,就是给上下文的属性Namespaces添加了一个以(区域注册对象所在命名空间+".*")的命名空间,这个最后会用于解析controller对象,通过后续代码可以看出,这个上下文的Namespaces会被使用。

      而一般的RegisterArea方法就是通过我们自己创建的区域注册对象来重写实现的,是通过调用AreaRegistrationContext对象的MapRoute()方法来实现路由注册的.

    public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces)
    {
          if (namespaces == null && this.Namespaces != null)
            namespaces = Enumerable.ToArray<string>((IEnumerable<string>) this.Namespaces);
          Route route = RouteCollectionExtensions.MapRoute(this.Routes, name, url, defaults, constraints, namespaces);
          route.DataTokens["area"] = (object) this.AreaName;
          bool flag = namespaces == null || namespaces.Length == 0;
          route.DataTokens["UseNamespaceFallback"] = (object) (bool) (flag ? 1 : 0);
          return route;
    }
    

      这个方法中我们看到如果注册路由时没有指定命名空间,则会把上下文的Namespaces属性拿来使用,除了注册路由之外,这个方法还做了一步工作,在路由数据的DataTokens中添加了一个以UseNamespaceFallback为key的数据,它的值是通过判断如果注册路由的命名空间参数和上下文的Namespaces都为空的情况下,为1,否则为0;为1,则在解析controller时需要使用controllerBuilder中的DefaultNamespaces属性的值中的命名空间。这个逻辑我们可以再DefaultControllerFactory的GetControllerType()方法中可以看到!

       而且我们可以看到路由数据RouteData中表示区域的area的值是存在DataTokens属性中

  • 相关阅读:
    json和xml数据的解析
    block(闭包)
    自定义控件注意点
    字符串使用
    如何用运行时,给系统分类添加属性?
    论代码规范
    常用设计模式
    多控制器管理
    GDI+学习及代码总结之-----画笔 .
    MFC程序添加Web浏览器控件(IE控件)
  • 原文地址:https://www.cnblogs.com/lpandnn/p/2888478.html
Copyright © 2020-2023  润新知