<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      asp.net mvc 之旅 —— 第五站 從源碼中分析asp.net mvc 中的TempData

        在mvc的controller中,我們知道有很多的臨時變量存放數據,比如說viewData,viewBag,還有一個比較特殊的tempData,關于前兩個或許大家都明白,

      基本上是一個東西,就是各自的編程寫法不一樣,最終都會放到viewContext中,然后送到WebPage中,如果你要證明的話,可以看下下面的代碼。

              /// <summary>Gets the dynamic view data dictionary.</summary>
              /// <returns>The dynamic view data dictionary.</returns>
              [Dynamic]
              public dynamic ViewBag
              {
                  [return: Dynamic]
                  get
                  {
                      if (this._dynamicViewDataDictionary == null)
                      {
                          this._dynamicViewDataDictionary = new DynamicViewDataDictionary(() => this.ViewData);
                      }
                      return this._dynamicViewDataDictionary;
                  }
              }
      
              /// <summary>Gets or sets the dictionary for view data.</summary>
              /// <returns>The dictionary for the view data.</returns>
              public ViewDataDictionary ViewData
              {
                  get
                  {
                      if (this._viewDataDictionary == null)
                      {
                          this._viewDataDictionary = new ViewDataDictionary();
                      }
                      return this._viewDataDictionary;
                  }
                  set
                  {
                      this._viewDataDictionary = value;
                  }
              }

      從上面的代碼中可以看到,其實ViewBag就是獲取ViewData的數據,對不對。。。

       

      一:TempData

          至于這個東西怎么用,大家貌似都記得是可訪問一次后即刻消失,好像貌似也就這樣了,當然不知道有沒有人對tempdata的底層代碼進行研究呢???

      看一下它的底層到底是怎么來實現的。

       

      1. TempData源代碼

          首先我們看一下TempData的類型是TempDataDictionary,可以看到這個類型肯定是實現了IDictionary接口的自定義字典,

              public TempDataDictionary TempData
              {
                  get
                  {
                      if (this.ControllerContext != null && this.ControllerContext.IsChildAction)
                      {
                          return this.ControllerContext.ParentActionViewContext.TempData;
                      }
                      if (this._tempDataDictionary == null)
                      {
                          this._tempDataDictionary = new TempDataDictionary();
                      }
                      return this._tempDataDictionary;
                  }
                  set
                  {
                      this._tempDataDictionary = value;
                  }
              }

      從上面代碼可以看到,tempdate默認是new了一個TempDataDictionary類,這個類中很好玩的地方在于這里有一個load方法,這個load方法就是獲取真

      正的provider,比如下面這樣:

              /// <summary>Loads the specified controller context by using the specified data provider.</summary>
              /// <param name="controllerContext">The controller context.</param>
              /// <param name="tempDataProvider">The temporary data provider.</param>
              public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
              {
                  IDictionary<string, object> dictionary = tempDataProvider.LoadTempData(controllerContext);
                  this._data = ((dictionary != null) ? new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase));
                  this._initialKeys = new HashSet<string>(this._data.Keys, StringComparer.OrdinalIgnoreCase);
                  this._retainedKeys.Clear();
              }

      這個load方法就是非常重要的,這里的參數ITempDataProvider就是我們在BeginExecute方法賦值的,繼續往下看,不要著急哦。。。

       

      2. BeginExecute

         我們知道,mvc框架其實是截獲了mvcroutehandler來進行截獲url的請求,繼而將后續的處理就由mvc框架來接管,最終會執行到Controller類下面的

      BeginExecute,如果你不信,我可以開心加愉快的給你上代碼,比如下面這樣:

              protected virtual IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)
              {
                  Action action2 = null;
                  if (this.DisableAsyncSupport)
                  {
                      if (action2 == null)
                      {
                          action2 = delegate {
                              this.Execute(requestContext);
                          };
                      }
                      Action action = action2;
                      return AsyncResultWrapper.BeginSynchronous(callback, state, action, _executeTag);
                  }
                  if (requestContext == null)
                  {
                      throw new ArgumentNullException("requestContext");
                  }
                  base.VerifyExecuteCalledOnce();
                  this.Initialize(requestContext);
                  BeginInvokeDelegate<Controller> beginDelegate = (asyncCallback, callbackState, controller) => controller.BeginExecuteCore(asyncCallback, callbackState);
                  EndInvokeVoidDelegate<Controller> endDelegate = delegate (IAsyncResult asyncResult, Controller controller) {
                      controller.EndExecuteCore(asyncResult);
                  };
                  return AsyncResultWrapper.Begin<Controller>(callback, state, beginDelegate, endDelegate, this, _executeTag, -1, null);
              }

      上面這段代碼中,你一定要看清楚上面標紅的地方,這里我們看到了,其實這里是一個異步的beginxxx,endxxx的操作,問題就是在這里,首先我們從

      beginInvoke說起。

       

      <1> beginDelegate

             這個異步操作中,我們可以看到,其實執行的是一個controller.BeginExecuteCore(asyncCallback, callbackState) 方法,對吧,然后我們可以

      感興趣的看一下這個方法干了什么?

              protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
              {
                  IAsyncResult result;
                  this.PossiblyLoadTempData();
                  try
                  {
                      Action action2 = null;
                      string actionName = GetActionName(this.RouteData);
                      IActionInvoker invoker = this.ActionInvoker;
                      IAsyncActionInvoker invoker = invoker as IAsyncActionInvoker;
                      if (invoker != null)
                      {
                          BeginInvokeDelegate<ExecuteCoreState> beginDelegate = (asyncCallback, asyncState, innerState) => innerState.AsyncInvoker.BeginInvokeAction(innerState.Controller.ControllerContext, innerState.ActionName, asyncCallback, asyncState);
                          EndInvokeVoidDelegate<ExecuteCoreState> endDelegate = delegate (IAsyncResult asyncResult, ExecuteCoreState innerState) {
                              if (!innerState.AsyncInvoker.EndInvokeAction(asyncResult))
                              {
                                  innerState.Controller.HandleUnknownAction(innerState.ActionName);
                              }
                          };
                          ExecuteCoreState invokeState = new ExecuteCoreState {
                              Controller = this,
                              AsyncInvoker = invoker,
                              ActionName = actionName
                          };
                          return AsyncResultWrapper.Begin<ExecuteCoreState>(callback, state, beginDelegate, endDelegate, invokeState, _executeCoreTag, -1, null);
                      }
                      if (action2 == null)
                      {
                          action2 = delegate {
                              if (!invoker.InvokeAction(this.ControllerContext, actionName))
                              {
                                  this.HandleUnknownAction(actionName);
                              }
                          };
                      }
                      Action action = action2;
                      result = AsyncResultWrapper.BeginSynchronous(callback, state, action, _executeCoreTag);
                  }
                  catch
                  {
                      this.PossiblySaveTempData();
                      throw;
                  }
                  return result;
              }

      從上面的代碼中,你應該看到了有一個 this.PossiblyLoadTempData()方法,看這個名字我們大概就可以猜得到這個方法和tempdate肯定有莫大的關系。

      說時遲那時快,我們可以看下這個方法到底干了什么。。。在一系列跟蹤之后,我們最后會到這個代碼里面去了,如下所示:

              internal void PossiblyLoadTempData()
              {
                  if (!base.ControllerContext.IsChildAction)
                  {
                      base.TempData.Load(base.ControllerContext, this.TempDataProvider);
                  }
              }

       

      請大家看清了,這里我們調用了剛才文章開頭出說到的Tempdata.Load方法,那么問題來了,這里的TempDataProvider到底是怎么來的。我們繼續來看代碼:

              public ITempDataProvider TempDataProvider
              {
                  get
                  {
                      if (this._tempDataProvider == null)
                      {
                          this._tempDataProvider = this.CreateTempDataProvider();
                      }
                      return this._tempDataProvider;
                  }
                  set
                  {
                      this._tempDataProvider = value;
                  }
              }

       

      看到沒有,然后TempDataProvider然來是調用了CreateTempDataProvider方法來實現的,下一步我們來看一下CreateTempDataProvider到底干了什么。

              protected virtual ITempDataProvider CreateTempDataProvider()
              {
                  ITempDataProviderFactory service = this.Resolver.GetService<ITempDataProviderFactory>();
                  if (service != null)
                  {
                      return service.CreateInstance();
                  }
                  return (this.Resolver.GetService<ITempDataProvider>() ?? new SessionStateTempDataProvider());
              }

      從上面這個代碼,我們應該就明白了,然來我們的tempdata默認是由SessionStateTempDataProvider來提供的,好了,接下來我們就可以繼續看看

      SessionStateTempDataProvider大概實現的業務邏輯。

        public class SessionStateTempDataProvider : ITempDataProvider
          {
              internal const string TempDataSessionStateKey = "__ControllerTempData";
              
              public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
              {
                  HttpSessionStateBase session = controllerContext.HttpContext.Session;
                  if (session != null)
                  {
                      Dictionary<string, object> dictionary = session["__ControllerTempData"] as Dictionary<string, object>;
                      if (dictionary != null)
                      {
                          session.Remove("__ControllerTempData");
                          return dictionary;
                      }
                  }
                  return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
              }
              
              public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
              {
                  if (controllerContext == null)
                  {
                      throw new ArgumentNullException("controllerContext");
                  }
                  HttpSessionStateBase session = controllerContext.HttpContext.Session;
                  bool flag = (values != null) && (values.Count > 0);
                  if (session == null)
                  {
                      if (flag)
                      {
                          throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
                      }
                  }
                  else if (flag)
                  {
                      session["__ControllerTempData"] = values;
                  }
                  else if (session["__ControllerTempData"] != null)
                  {
                      session.Remove("__ControllerTempData");
                  }
              }
          }

      可以看到,SessionStateTempDataProvider 是實現了ITempDataProvider接口,里面有兩個方法LoadTempData 和SaveTempData方法,而

      LoadTempData方法的邏輯很奇葩,你可以仔細觀察一下哦,如果 if (session != null)滿足就清空字典的數據,否則就不清除,這個邏輯大概就向

      你展示了為什么數據只能被讀取一次,下次讀取的時候,就走了這個if(session!=null)給清空了,你怎么可能再讀取session中的數據呢。。。這個

      就是為什么tempdata只能被讀取一次的真相,是不是很好玩。

       

      <2> EndExecuteCore

          有人可能會問了,第二個方法SaveTempData是什么時候執行的,當然就是EndExecuteCore里面了,比如你看:

              protected virtual void EndExecuteCore(IAsyncResult asyncResult)
              {
                  try
                  {
                      AsyncResultWrapper.End(asyncResult, _executeCoreTag);
                  }
                  finally
                  {
                      this.PossiblySaveTempData();
                  }
              }

      可以看到它的默認實現是session,當然你也可以實現一個自定義的provider,比如用cache來存放這個臨時數據,或者是redis,mongodb等等。。。

      當然還有更多有趣的東西等待你發掘哦~~~

       

      posted @ 2016-07-12 15:34  一線碼農  閱讀(3100)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 亚洲产国偷v产偷v自拍色戒| 蜜臀视频一区二区在线播放| 亚洲欧洲日产国码无码久久99 | 亚洲午夜福利网在线观看| 亚洲一区二区中文av| 国产人妻一区二区三区四区五区六 | 久久精品国产91久久麻豆| 蜜桃网址| 18禁无遮挡啪啪无码网站破解版| 国产av熟女一区二区三区| 一级国产在线观看高清| 久久一亚色院精品全部免费| 国产偷窥熟女高潮精品视频| 成人免费看片又大又黄| 国产久免费热视频在线观看| 中文字幕在线精品人妻| 婷婷成人丁香五月综合激情| 国产成人一卡2卡3卡四卡视频 | 少妇无码AV无码专区| 亚洲国产欧美一区二区好看电影| 91精品国产蜜臀在线观看| 日日躁夜夜躁狠狠躁超碰97 | 久久久久国产精品熟女影院| 国产视频深夜在线观看| 一本色道国产在线观看二区| 国产精品成人aaaaa网站| 自慰无码一区二区三区| 暖暖影院日本高清...免费| 亚洲高清偷拍一区二区三区| 麻江县| 亚洲成在人线在线播放无码| 色综合久久久久综合体桃花网 | 十八禁国产一区二区三区| av性色av久久无码ai换脸| 久久精品国产亚洲夜色av| 人妻少妇偷人精品一区| 四虎国产精品免费久久久| 国产精品99久久不卡| 日本一卡2卡3卡4卡无卡免费| 国产在线精彩自拍视频| 人妻少妇精品视频专区|