• 自定义TempData跨平台思路


    一:TempData的自定义实现。。。

    TempData是用Session实现的,既然是Session,那模式是线程方式。。。这样的Session是没法进行跨平台的。。。

    那么这就涉及到如何在多台机器上部署、存储...

    • 关系型数据库: sqlserver/mysql
    • nosql: mongodb,redis。

    问题1:重点在替换,不在实现。。。。。怎么替换,以及使用方式

    TempData继承关系:Tempdata => TempDataDictionary=> SessionStateTempDataProvider=>ITempDataProvider

     1 namespace System.Web.Mvc
     2 {
     3     using System;
     4     using System.Collections.Generic;
     5     using System.Web;
     6     using System.Web.Mvc.Properties;
     7     
     8     public class SessionStateTempDataProvider : ITempDataProvider
     9     {
    10         internal const string TempDataSessionStateKey = "__ControllerTempData";
    11         
    12         public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
    13         {
    14             HttpSessionStateBase session = controllerContext.HttpContext.Session;
    15             if (session != null)
    16             {
    17                 Dictionary<string, object> dictionary = session["__ControllerTempData"] as Dictionary<string, object>;
    18                 if (dictionary != null)
    19                 {
    20                     session.Remove("__ControllerTempData");
    21                     return dictionary;
    22                 }
    23             }
    24             return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    25         }
    26         
    27         public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    28         {
    29             if (controllerContext == null)
    30             {
    31                 throw new ArgumentNullException("controllerContext");
    32             }
    33             HttpSessionStateBase session = controllerContext.HttpContext.Session;
    34             bool flag = (values != null) && (values.Count > 0);
    35             if (session == null)
    36             {
    37                 if (flag)
    38                 {
    39                     throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
    40                 }
    41             }
    42             else if (flag)
    43             {
    44                 session["__ControllerTempData"] = values;
    45             }
    46             else if (session["__ControllerTempData"] != null)
    47             {
    48                 session.Remove("__ControllerTempData");
    49             }
    50         }
    51     }
    52 }

    SessionStateTempDataProvider类实现了ITempDataProvider接口,重写了Load和Save方法。

    从源码可知,SessionStatesTempDataProvider暴露了LoadTempData和SaveTempData两个方法。

    其中从SaveTempData中session["__ControllerTempData"] = (object) values;可以看出,TempData是存储在Session中的。

    其中LoadTempData方法中session.Remove("__ControllerTempData");就说明了从session中获取tempdata后,对应的tempdata就从session中清空了

    问题2:到底在mvc中哪个地方进行注入????mvc的管道中是怎么注入的???

    MVC的管道和action方法执行前后发现:PossiblyLoadTempData和PossiblySaveTempData是在调用Controller中对应的action方法时执行的,并且Controller中有 TempDataProvider属性,代码如下:

     1 public ITempDataProvider TempDataProvider
     2         {
     3             get
     4             {
     5                 if (this._tempDataProvider == null)
     6                 {
     7                     this._tempDataProvider = this.CreateTempDataProvider();
     8                 }
     9                 return this._tempDataProvider;
    10             }
    11             set
    12             {
    13                 this._tempDataProvider = value;
    14             }
    15         }

    所以注入点就找到了,在创建Controller Factory中创建Controller实例的时候,把自定义的DataProvider类,赋值给TempDataProvider就可以了

    下面来实现一把分布式的tempData

    实现分布式流程

    继承自DefaultControllerFactory的MyControllerFactory类即自定义的Controller Factory

    1 public class MyControllerFactory:DefaultControllerFactory
     2     {
     3         public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
     4         {
     5             var iController= base.CreateController(requestContext, controllerName);
     6 
     7             var controller = iController as Controller;
     8             controller.TempDataProvider = new CrossSessionTempData2();
     9 
    10 
    11             return iController;
    12         }
    13     }

    TempData的值存入到cache中之文件依赖

    接着我们需要自定义一个实现了ITempDataProvider接口的DataProvider类

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 using System.Web.Caching;
     6 using System.Web.Mvc;
     7 
     8 namespace CrossSessionTempData.Infrastructure
     9 {
    10     public class CrossSessionTempData2 : ITempDataProvider
    11     {
    12 
    13         internal const string TempDataSessionStateKey = "__ControllerTempData";
    14 
    15         public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
    16         {
    17             var cache = controllerContext.HttpContext.Cache;
    18 
    19             if (cache != null)
    20             {
    21                 Dictionary<string, object> dictionary = cache[TempDataSessionStateKey] as Dictionary<string, object>;
    22                 if (dictionary != null)
    23                 {
    24                     //cache.Remove(TempDataSessionStateKey);
    25                     return dictionary;
    26                 }
    27             }
    28             return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    29         }
    30 
    31         /// <summary>Saves the specified values in the temporary data dictionary by using the specified controller context.</summary>
    32         /// <param name="controllerContext">The controller context.</param>
    33         /// <param name="values">The values.</param>
    34         /// <exception cref="T:System.InvalidOperationException">An error occurred the session context was being retrieved.</exception>
    35         public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    36         {
    37             if (controllerContext == null)
    38             {
    39                 throw new ArgumentNullException("controllerContext");
    40             }
    41             var cache = controllerContext.HttpContext.Cache;
    42             bool flag = values != null && values.Count > 0;
    43             if (cache == null)
    44             {
    45                 if (flag)
    46                 {
    47                     throw new InvalidOperationException("");
    48                 }
    49             }
    50             else
    51             {
    52                 CacheDependency dp = new CacheDependency(controllerContext.HttpContext.Server.MapPath("/Data/123.txt"));
    53                 if (flag)
    54                 {
    55                     
    56 
    57                     //cache[TempDataSessionStateKey] = values;
    58                     cache.Insert(TempDataSessionStateKey, values, dp);
    59 
    60                     return;
    61                 }
    62                 cache.Insert(TempDataSessionStateKey, values, dp);
    63                 //if (cache[TempDataSessionStateKey] != null)
    64                 //{
    65                 //    cache.Remove(TempDataSessionStateKey);
    66                 //}
    67             }
    68         }
    69     }
    70 }

    把TempData的值存入到NoSQL Memcached中实现真正的分布式

    1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 using Memcached.ClientLibrary;
     6 
     7 namespace WebDemo.Models
     8 {
     9     public static class MemcacheHelper
    10     {
    11         private static MemcachedClient mc;
    12 
    13         static MemcacheHelper()
    14         {
    15             //通过客户端来进行memcached的集群配置,在插入数据的时候,使用一致性哈希算法,将对应的value值存入Memcached
    16             String[] serverlist = { "127.0.0.1:11211" };
    17 
    18             // 初始化Memcached的服务池
    19             SockIOPool pool = SockIOPool.GetInstance("test");
    20             //设置服务器列表
    21             pool.SetServers(serverlist);
    22             //各服务器之间负载均衡的设置比例
    23             pool.SetWeights(new int[] { 1 });
    24             pool.Initialize();
    25             //创建一个Memcached的客户端对象
    26             mc = new MemcachedClient();
    27             mc.PoolName = "test";
    28             //是否启用压缩数据:如果启用了压缩,数据压缩长于门槛的数据将被储存在压缩的形式
    29             mc.EnableCompression = false;
    30             
    31         }
    32         /// <summary>
    33         /// 插入值
    34         /// </summary>
    35         /// <param name="key"></param>
    36         /// <param name="value"></param>
    37         /// <param name="expiry">过期时间</param>
    38         /// <returns></returns>
    39         public static bool Set(string key, object value,DateTime expiry){
    40             return mc.Set(key, value, expiry);
    41         }
    42         /// <summary>
    43         /// 获取值
    44         /// </summary>
    45         /// <param name="key"></param>
    46         /// <returns></returns>
    47         public static object Get(string key)
    48         {
    49             return mc.Get(key);
    50         }
    51     }
    52 }

    自定义的我们的DataProvider:

    1  public class CrossSessionTempData2 : ITempDataProvider
     2     {
     3 
     4         internal const string TempDataSessionStateKey = "__ControllerTempData";
     5 
     6         public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
     7         {
     8           
     9             Dictionary<string, object> dictionary = MemCaheHelper.Get(TempDataSessionStateKey) as Dictionary<string, object>;
    10             if (dictionary != null)
    11             {
    12                 MemCaheHelper.Set(TempDataSessionStateKey, dictionary, DateTime.MinValue);
    13                 return dictionary;
    14             }
    15             return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    16         }
    17 
    18         public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    19         {
    20             if (controllerContext == null)
    21             {
    22                 throw new ArgumentNullException("controllerContext");
    23             }
    24             
    25             bool flag = values != null && values.Count > 0;
    26             if (flag)
    27             {
    28                
    29                 MemCaheHelper.Set(TempDataSessionStateKey, values,DateTime.Now.AddMinutes(1));
    30                 return;
    31             }
    32 
    33             if (MemCaheHelper.Get(TempDataSessionStateKey) != null)
    34             {
    35                 MemCaheHelper.Set(TempDataSessionStateKey,values,DateTime.MinValue);
    36             }
    37           
    38 
    39         }
    40     }
  • 相关阅读:
    Go 指针
    Go 字符串
    Go Maps
    Go 可变参数函数
    Go 数组和切片
    pyqt5实现窗口跳转并关闭上一个窗口
    spy++查找窗口句柄
    Python中Tk模块简单窗口设计
    pyqt5无边框拖动
    pyqt5 GUI教程
  • 原文地址:https://www.cnblogs.com/cuijl/p/7412793.html
Copyright © 2020-2023  润新知