美文网首页
Asp.Net Session 自定义之 使用 RedisSes

Asp.Net Session 自定义之 使用 RedisSes

作者: 无为无味无心 | 来源:发表于2018-11-05 10:29 被阅读0次

注意:存储在这种Redis Seesion中的一定不能是内部类的实例,否则会引起Session 在管道事件中卡顿,目前暂时没找到原因
2 配置文件配置如下:

<system.web>
    <sessionState mode="Custom" customProvider="RedisSessionStateStore">
      <providers>
        <add name="RedisSessionStateStore" type="Custom_RedisSessionStateStore.RedisDemo.RedisSessionStateStore"/>
      </providers>
    </sessionState>
</system.web>

1 编写类 RedisSessionStateStore

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using Com.Redis;
using System.Collections.Specialized;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;

namespace Custom_RedisSessionStateStore.RedisDemo
{
    /// <summary>
    /// 使用Cookie实现SessionStateStoreProviderBase
    /// 注意:它只适合保存简单的基元类型数据。
    /// </summary>
    public class RedisSessionStateStore : SessionStateStoreProviderBase
    {
        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            return CreateLegitStoreData(context, null, null, timeout);
        }

        internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
        {
            if (sessionItems == null)
                sessionItems = new SessionStateItemCollection();
            if (staticObjects == null && context != null)
                staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
            return new SessionStateStoreData(sessionItems, staticObjects, timeout);
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            RedisSessionState state = new RedisSessionState(null, null, timeout);
            RedisBase.Item_Set<string>(id, state.ToJson(), timeout);
        }

        private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
        {
            locked = false;
            lockId = null;
            lockAge = TimeSpan.Zero;
            actionFlags = SessionStateActions.None;
            RedisSessionState state = RedisSessionState.FromJson(RedisBase.Item_Get<string>(id));
            if (state == null)
            {
                return null;
            }
            RedisBase.Item_SetExpire(id, state._timeout);
            return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout);
        }

        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
        {
            return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags);
        }

        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
        {
            return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags);
        }

        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            ISessionStateItemCollection sessionItems = null;
            HttpStaticObjectsCollection staticObjects = null;

            if (item.Items.Count > 0)
                sessionItems = item.Items;
            if (!item.StaticObjects.NeverAccessed)
                staticObjects = item.StaticObjects;

            RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout);

            RedisBase.Item_Set<string>(id, state2.ToJson(), item.Timeout);
        }

        #region "未实现方法"

        public override void Dispose()
        {

        }

        public override void EndRequest(HttpContext context)
        {

        }

        public override void InitializeRequest(HttpContext context)
        {

        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            RedisBase.Item_Remove(id);
        }

        public override void ResetItemTimeout(HttpContext context, string id)
        {

        }

        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            return true;
        }

        #endregion

    }
    internal sealed class SessionStateItem
    {
        public Dictionary<string, SaveValue> Dict;
        public int Timeout;
    }

    internal sealed class SaveValue
    {
        public object Value { get; set; }

        public Type Type { get; set; }
    }

    internal sealed class RedisSessionState
    {
        internal ISessionStateItemCollection _sessionItems;
        internal HttpStaticObjectsCollection _staticObjects;
        internal int _timeout;

        internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
        {
            this.Copy(sessionItems, staticObjects, timeout);
        }

        internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
        {
            this._sessionItems = sessionItems;
            this._staticObjects = staticObjects;
            this._timeout = timeout;
        }

        public string ToJson()
        {
            // 这里忽略_staticObjects这个成员。

            if (_sessionItems == null || _sessionItems.Count == 0)
            {
                return null;
            }

            Dictionary<string, SaveValue> dict = new Dictionary<string, SaveValue>(_sessionItems.Count);

            NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys;
            string key;
            object objectValue = string.Empty;
            Type type = null;
            for (int i = 0; i < keys.Count; i++)
            {
                key = keys[i];
                objectValue = _sessionItems[key];
                if (objectValue != null)
                {
                    type = objectValue.GetType();
                }
                else
                {
                    type = typeof(object);
                }
                dict.Add(key, new SaveValue { Value = objectValue, Type = type });
            }

            SessionStateItem item = new SessionStateItem { Dict = dict, Timeout = this._timeout };

            return JsonConvert.SerializeObject(item);
        }

        public static RedisSessionState FromJson(string json)
        {
            if (string.IsNullOrEmpty(json))
            {
                return null;
            }
            try
            {
                SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json);

                SessionStateItemCollection collections = new SessionStateItemCollection();

                SaveValue objectValue = null;

                JsonSerializer serializer = new JsonSerializer();
                StringReader sr = null;
                JsonTextReader tReader = null;

                foreach (KeyValuePair<string, SaveValue> kvp in item.Dict)
                {
                    objectValue = kvp.Value as SaveValue;
                    if (objectValue.Value == null)
                    {
                        collections[kvp.Key] = null;
                    }
                    else
                    {
                        if (!IsValueType(objectValue.Type))
                        {
                            sr = new StringReader(objectValue.Value.ToString());
                            tReader = new JsonTextReader(sr);
                            collections[kvp.Key] = serializer.Deserialize(tReader, objectValue.Type);
                        }
                        else
                        {
                            collections[kvp.Key] = objectValue.Value;
                        }
                    }
                }

                return new RedisSessionState(collections, null, item.Timeout);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 判断是否为值类型
        /// </summary>
        /// <param name="type">Type</param>
        /// <returns></returns>
        public static bool IsValueType(Type type)
        {
            if (type.IsValueType)
            {
                return true;
            }
            //基础数据类型
            if (type == typeof(string) || type == typeof(char)
                || type == typeof(ushort) || type == typeof(short) || type == typeof(uint) || type == typeof(int)
                || type == typeof(ulong) || type == typeof(long) || type == typeof(double) || type == typeof(decimal)
                || type == typeof(bool)
                || type == typeof(byte))
            {
                return true;
            }
            //可为null的基础数据类型
            if (type.IsGenericType && !type.IsGenericTypeDefinition)
            {
                Type genericType = type.GetGenericTypeDefinition();

                if (Object.ReferenceEquals(genericType, typeof(Nullable<>)))
                {
                    var actualType = type.GetGenericArguments()[0];
                    return IsValueType(actualType);

                }
            }
            return false;
        }
    }
}

相关文章

网友评论

      本文标题:Asp.Net Session 自定义之 使用 RedisSes

      本文链接:https://www.haomeiwen.com/subject/zwwjxqtx.html