日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET MVC4学习笔记之Controller的激活

發布時間:2025/3/14 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET MVC4学习笔记之Controller的激活 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 高層相關類說明

  當路由系統根據請求Url收集路由信息后,下一步就要將路由信息傳給Controller激活系統,Controller激活系統負責實現了IController接口的Controller類實例化。它的相關類族體系如下圖所示:

MvcHandler實現了IHttpHandler,?IHttpAsyncHandler,IRequiresSessionState三個接口,其中IHttpHandler,?IHttpAsyncHandler分別是HttpHandler同步與異步的實現,IRequiresSessionState是個標記接口,表示需要Session支持.?

IController, IAsyncController,?ControllerBase, Controller 是一個繼承體系,IController是控制器接口,只定義了一個方法Execute方法表示執行入口,

IAsyncController是控制器的異步執行版本,ControllerBase是控制器基類,為控制器執行做一些初始化和環境準備工作,實現了Execute方法并在其內調用保護的抽像方法ExecuteCore.這個地方應用了Templete Method模式.?Controller實現了一堆接口, 為我們編程提供方便,?定義了大量的屬性和方法,具體的后面章節專門講解.

IControllerFactory 表示的是控制器的創建工廠,其中定義了三個方法,?CreateController方法創建IController的實例,?GetControllerSessionBehavior方法獲取Controller的會話行為,我們可以在自定義的Controller的上應用SessionStateAttribute指定會話行為。ReleaseController負責釋放使用完的Controller實例。

public interface IControllerFactory
{
  IController CreateController(RequestContext requestContext, string controllerName);
  SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
  void ReleaseController(IController controller);
}

ControllerBuilder 是負責實例化IController和IControllerFactory的接口,封裝具體的創建算法。提供了一個靜態只讀屬性Current表示當前的ControllerBuilder對象。

二. MvcHandler中IController與IControllerFactory的創建與執行

1. 主體過程ProcessRequest方法,代碼如下所示, 創建的過程委托給私有方法ProcessRequestInit

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
  IController controller;
  IControllerFactory factory;
  ProcessRequestInit(httpContext, out controller, out factory);

  try
  {
    controller.Execute(RequestContext);
  }
  finally
  {
    factory.ReleaseController(controller);
  }
}

?2.?ProcessRequestInit方法的主要代碼如下所示,我們可以看到最終的創建工作是交給了ControllerBuilder對象.

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
  //其它代碼
  // Get the controller type
  string controllerName = RequestContext.RouteData.GetRequiredString("controller");

  // Instantiate the controller and call Execute
  factory = ControllerBuilder.GetControllerFactory();
  controller = factory.CreateController(RequestContext, controllerName);
  if (controller == null)
  {
    throw new InvalidOperationException(...)
  }
}

?三.ControllerBuilder解析

 1.接口定義如下:

  public class ControllerBuilder

  {
    public ControllerBuilder();

    public static ControllerBuilder Current { get; } ?//
    public HashSet<string> DefaultNamespaces { get; } //默認命名空間,用于Controller類型解析過程

    public IControllerFactory GetControllerFactory();?
    public void SetControllerFactory(IControllerFactory controllerFactory); //設置自定義ControllerFactory
    public void SetControllerFactory(Type controllerFactoryType); //設置自定義ControllerFactory的類型,?
  }

  ControllerBuilder主要封裝了IControllerFactory的創建過程,也許命名叫ControllerFactoryBuilder更合適,從接口可以看出,我們可以傳入自定義

實現的IControllerFactory。

 2. 內部引用的幾個主要類說明:

  

   IResolver<T> 只定義了一個泛型屬性,表示獲取相關類型的一個實例;

   SingleServiceResolver<TService> 顧名思義,表示單一服務類型解析,它實現在了IResolver接口, 在ControllerBuilder內部使用的是SingleServiceResolver<IControllerFactory>;

   DefaultControllerFactory 系統提供的默認的Controller創建工廠實現;

?3. 內部IControllerFactory創建過程

   ?在ControllerBuilder實例化時,調用默認構造函數,而默認構造函數調用如下的內部構造函數,serviceResolver傳值為null,

  internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)

  {
    _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
       () => _factoryThunk(),
       new DefaultControllerFactory { ControllerBuilder = this },
        "ControllerBuilder.GetControllerFactory");
  }

  _factoryTunk() 是一個返回IControllerFactory的委托(Func<IControllerFactory>),默認值是() => null; 其主要目的是當傳入自定義IControllerFactory時做統一處理,

  public void SetControllerFactory(IControllerFactory controllerFactory)

  {
    _factoryThunk = () => controllerFactory;
  }

  ControllerBuilder返回IControllerFactory的方法內部實現如下:

  public IControllerFactory GetControllerFactory()
  {
    return _serviceResolver.Current;
  }

? ? 從上面的代碼中我們可以看出Factory的創建過程進一步委托給了SingleServiceResolver對象,現在我們看看SingleServiceResolver究竟是怎么創建對象的

.SingleServiceResolver<TService> 類型

? SingleServiceResolver其實ASP.NET MVC許多基礎類型創建所遵詢的一個模式. 它的構造函數如下:

  public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName)

  {
    //省略檢查代碼

    _resolverThunk = () => DependencyResolver.Current; //??DependencyResolver.Current表示系統全局的對象解析器
    _currentValueFromResolver = new Lazy<TService>(GetValueFromResolver); ?//從全局的Resolver器中創建對象
    _currentValueThunk = currentValueThunk; //當前傳入的創建委托
    _defaultValue = defaultValue; ? //默認值
    _callerMethodName = callerMethodName;
  }

  返回實例的代碼如下

  public TService Current
  {
    get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
  }

? ? ? 從中我們可以看出SingleServiceResolver解析對象的過程:

  1. 首先從嘗試從全局的對象解析器(DependencyResolver)中創建對象

  2. 否則嘗試利用當前的功能委托來創建對象

  3. 最后返回對象的默認值

? ? 在IControllerFactory創建中,默認情況下第1種和第2種情況都不起作用,所以返回的是DefaultControllerFactory, 現在我們終于得到了IControllerFactory實例,現在來看看它是怎么生成Controller實例的。

五.DefaultControllerFactory解析

  DefaultControllerFactory實現了IControllerFactory, 故名思義,它的主要作用就是Controller實例的創建與釋放,會話模式的獲取。

?1. Controller類型的實例化

  Controller實例的創建實現在CreateController方法中,主要的代碼如下:

  public virtual IController CreateController(RequestContext requestContext, string controllerName)

  {
    //省略其它代碼
    Type controllerType = GetControllerType(requestContext, controllerName);
    IController controller = GetControllerInstance(requestContext, controllerType);
    return controller;
  }

  可以看到分成了兩步走,首先查找確定Controller的類型,接著再利用類型創建其實例。下面來具體的看看相關的方法

  1.1 Controller類型的查找

  類型的查找實現在GetControllerType方法中,代碼如下:

  protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName)

  {

    // 省略其它代碼

    //1. 首先檢查在定制路由規則時指定的命名空間

    object routeNamespacesObj;

    Type match;

    if (requestContext != null && routeData.DataTokens.TryGetValue(RouteDataTokenKeys.Namespaces, out routeNamespacesObj))
    {
      IEnumerable<string> routeNamespaces = routeNamespacesObj as IEnumerable<string>;
      if (routeNamespaces != null && routeNamespaces.Any())
      {
        HashSet<string> namespaceHash = new HashSet<string>(routeNamespaces, StringComparer.OrdinalIgnoreCase);
        match = GetControllerTypeWithinNamespaces(routeData.Route, controllerName, namespaceHash);

        // the UseNamespaceFallback key might not exist, in which case its value is implicitly "true"
        if (match != null || false.Equals(routeData.DataTokens[RouteDataTokenKeys.UseNamespaceFallback]))
        {
          // got a match or the route requested we stop looking
          return match;
        }
      }
    ??}

  // 檢查默認的命名空間
  if (ControllerBuilder.DefaultNamespaces.Count > 0)
  {
    HashSet<string> namespaceDefaults = new HashSet<string>(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase);
    match = GetControllerTypeWithinNamespaces(routeData.Route, controllerName, namespaceDefaults);
    if (match != null)
    {
      return match;
    }
  }

  //檢查所有的命名空間,也就是只要有Controller名唯一匹配的就返回相應的Controller類型
  return GetControllerTypeWithinNamespaces(routeData.Route, controllerName, null /* namespaces */);
}?

? ?這個方法是查找Controller類型的骨架,查找是由三個層次的命名空間組成,

 1.首先從制定路由規則時指定的命名空間中查找,但一般我們指定路由規則時沒有指定命名空間,這里有還有一個參數UseNamespaceFallback表示是否查找后備命名空間,這個參數默認為true.?

? 2. 從默認的命名空間ControllerBuilder.DefaultNamespaces中查找

? 3. 從所有的命名空間中查找,查找唯一能匹配的Controller

? 在以上查找中,都會調用GetControllerTypeWithinNamespaces方法,現在來看看這個方法的實現

  private Type GetControllerTypeWithinNamespaces(RouteBase route, string controllerName, HashSet<string> namespaces)
  {
    // Once the master list of controllers has been created we can quickly index into it
    ControllerTypeCache.EnsureInitialized(BuildManager);

    ICollection<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
    switch (matchingTypes.Count)
    {
      case 0:
      // no matching types
        return null;

      case 1:
      // single matching type
        return matchingTypes.First();

      default:
        // multiple matching types
      throw CreateAmbiguousControllerException(route, controllerName, matchingTypes);
    }
  ?}

   從以上的代碼中我們可以看到查找工作又進一步委托給了ControllerTypeCache這個內部類型,這個類型是特意為實現快速查找Controller類型而設計的一個數據結構,在內部它把所有的Controller通過反射把數據組織成如下形式:

   controllerAName ? ? ?namespace1, ?Type

            ? ? ?namespace2, ? Type

   controllerBName ? ? namespace1, ?Type

            ? ? ?namespace2, ? Type

?            ...

  當我們調用ControllerTypeCache.GetControllerTypes,傳入controllerName, namespaces參數時,首先會通過controllerName得到匹配的namespace和Type列表,

再利用傳入的namespaces參數與列表中的每個namespace進行比較,匹配則將相應的類型加入返回列表,如果傳入的namespaces為null, 則直接將列表中所有的類型都加入返回列表,在GetControllerTypeWithinNamespaces方法中我們檢查返回結果,如果只有一個類型,這是我們想要的結果,則直接返回,有一個以上則拋出Ambiguous異常。至此我們確定了Controller的類型,現在來看看Controller的實例化。

? ? 1.2 Controller類型的實例化

?   在前面我們已經看到,Controller類型實例化是實現在GetControllerInstance方法中,代碼如下:

    protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)

    {

      //省略非關鍵代碼
      return ControllerActivator.Create(requestContext, controllerType);
    }

  直接調用了ControllerActivator來創建實例,ControllerActivator是一個類型為IControllerActivator的屬性,IControllerActivator的定義如下:

   public interface IControllerActivator

  {
    IController Create(RequestContext requestContext, Type controllerType);
  }

  具體來看看ControllerActivator屬性的定義,

   ?private IControllerActivator ControllerActivator
   {
      get
      {
        if (_controllerActivator != null)
        {
          return _controllerActivator;
        }
        _controllerActivator = _activatorResolver.Current;
        return _controllerActivator;
      }
  }

  這里_controllerActivator在DefaultControllerFactory構造函數中初始化,代表傳入自定義的Controller激活器.具有最高的優先級。

_activatorResolver是IResolver<IControllerActivator>類型, 也是在構造函數中初始化,允許自定義實現IResolver<IControllerActivator>,具有第二高的優先級,

但在默認情況一下,前面兩個參數都為null,?_activatorResolver被實例化為SingleServiceResolver<IControllerActivator>類型。具體我們來看看DefaultControllerFactory的構造函數:

  internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver     dependencyResolver)

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

  SingleServiceResolver<T>泛型類前面已分析,這里不再贅述,從上面的代碼中我們看到,默認情況下Controller實例化最終落在了DefaultControllerActivator的頭上,

再來看看該類型的實現:

  private class DefaultControllerActivator : IControllerActivator

  {
    private Func<IDependencyResolver> _resolverThunk;

    public DefaultControllerActivator()
      : this(null)
    {
    }

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

   public IController Create(RequestContext requestContext, Type controllerType)
   {
    ?try
    ?{
      return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
    }
    catch (Exception ex)
    {
      throw new InvalidOperationException(...)
    }
   }
  }

   DefaultControllerActivator構造函數允許傳一個IDependencyResolver 對象,從上面的代碼中我們可以看出,優先使用該對象創建Conroller實例,

如果該對象為null,則嘗試使用系統默認的DependencyResolver,如果前面的兩者IDependencyResolver創建失敗,再使用Activator.CreateInstance實列化.

在默認情況一下,Controller實例是通過DependencyResolver.Current實列化,最終也是調用Activator.CreateInstance實例化的。

?2. Controller實例的釋放

   釋放的實現代碼很簡單,即檢查Controller是否實現了IDisposable 接口,如果實現該接口則調用其Dispose()方法。

  public virtual void ReleaseController(IController controller)

  {
    IDisposable disposable = controller as IDisposable;
    if (disposable != null)
    {
      disposable.Dispose();
    }
  }

3.Controller會話行為的設置

  3.1 會話行為獲取

    controller會話行為的獲取是通過反射得到應用在Controller上的SessionStateAttribute,具體的實現在代碼在GetControllerSessionBehavior中,

    protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
    {
      if (controllerType == null)
      {
        return SessionStateBehavior.Default;
      }

      return _sessionStateCache.GetOrAdd(
        controllerType,
        type =>
        {
          var attr = type.GetCustomAttributes(typeof(SessionStateAttribute), inherit: true)
          .OfType<SessionStateAttribute>()
          .FirstOrDefault();

          return (attr != null) ? attr.Behavior : SessionStateBehavior.Default;
      });
    }

    從上面的代碼中可以看出,如果沒在Controller上的指定特別的Session行為,會返回SessionStateBehavior.Default,表示由IHttpHandler實現的會話標記接口來確定會話行為,MvcHandler標記了IRequiresSessionState,表示Session可讀可寫.

  3.2 會話行為設置

    會話行為設置是在MvcRouteHandler中,具本的代碼如下:

    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)

    {

      //設置會話行為
      requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
      return new MvcHandler(requestContext);
    }

    protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
    {

      //省略非關鍵代碼

      IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
      return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
    }

六總結

    在本小節中,我們在源代碼級別分析了ControllerFacotry和Controller實例的創建過程,從中可以看出ASP.NET MVC框架定義很多的擴展點,

? 下一節我們來看看具體Controller激活相關的擴展應用。

轉載于:https://www.cnblogs.com/jjyjjyjjy/p/3597647.html

總結

以上是生活随笔為你收集整理的ASP.NET MVC4学习笔记之Controller的激活的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。