ASP.NET当前会话对象-注入日志逻辑

本文关键字:注入 日志 对象 NET 会话 ASP | 更新日期: 2023-09-27 18:21:40

在我正在开发的应用程序中,我们使用的是InProc ASP.NET SessionState对象。

我想找到一种方法,每当有代码读取或写入Session对象时,都可以记录消息。

我知道Item[]索引,我想我应该以某种方式注入代码。。或者可能继承HttpSessionState类?

选项、想法、经验。。。?

ASP.NET当前会话对象-注入日志逻辑

只是一个加法。

(编辑:我让它更通用了一点)

首先,一个抽象包装的接口

interface ISessionStateItemCollectionWrapper : ISessionStateItemCollection
{
    ISessionStateItemCollection WrappedCollection { get; set; }
}

由于我想在读取或写入会话项时进行日志记录,我为ISessionStateItemCollection 添加了一个包装器

public class SessionStateItemCollectionWithInstrumentation : ISessionStateItemCollectionWrapper
{
    public ISessionStateItemCollection WrappedCollection { get; set; }
        //...
        //...
        //...
        public object this[string name]
        {
            get
            {
                LogRead();
                return _wrappedCollection[name];
            }
            set
            {
                LogWrite();
                _wrappedCollection[name] = value;
            }
        }
        //...
        //More log on some methods
        //...
    }

然后,为了注入它,我继承了SessionStateStoreData

class SessionStoreDataItemsInjector<T> : SessionStateStoreData where T:ISessionStateItemCollectionWrapper, new()
{
    public SessionStoreDataItemsInjector(SessionStateStoreData wrappedData)
        : base(new T()
        {
            WrappedCollection = wrappedData.Items
        }, wrappedData.StaticObjects, wrappedData.Timeout)
    {
    }
}

然后我把它连接到唐提供的类

abstract class InProcSessionStateInjected<T> : SessionStateStoreProviderBase where T : ISessionStateItemCollectionWrapper, new()
{
    private SessionStateStoreProviderBase inProcSessionStore;
    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
    {
        var inProcSessionStoreType = typeof(SessionStateStoreProviderBase).Assembly.GetType("System.Web.SessionState.InProcSessionStateStore");
        inProcSessionStore = (SessionStateStoreProviderBase)Activator.CreateInstance(inProcSessionStoreType);
        inProcSessionStore.Initialize(name, config);
    }
    public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
    {
        var sessionStateStoreData = inProcSessionStore.CreateNewStoreData(context, timeout);
        return sessionStateStoreData.Items.GetType() != typeof(T) ? new SessionStoreDataItemsInjector<T>(sessionStateStoreData) : sessionStateStoreData;
    }
    public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
    {
        var sessionStateStoreData = inProcSessionStore.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
        if (sessionStateStoreData != null && sessionStateStoreData.Items.GetType() != typeof(T))
        {
            return new SessionStoreDataItemsInjector<T>(sessionStateStoreData);
        }
        return sessionStateStoreData;
    }
    public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
    {
        var sessionStateStoreData = inProcSessionStore.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
        if (sessionStateStoreData != null && sessionStateStoreData.Items.GetType() != typeof(T))
        {
            return new SessionStoreDataItemsInjector<T>(sessionStateStoreData);
        }
        return sessionStateStoreData;
    }

您可以创建一个自定义SessionStateProvider,并从该提供程序中实例化InProcSessionStateStore的实例,并使用它来完成与会话存储处理相关的所有工作。

从这个自定义SessionStateProvider中,您可以执行所有日志记录。

所以你必须做的是:

  1. 创建一个继承SessionStateStoreProviderBase类的新类,假设其名称为"MySessionStateProvider"

  2. 实现所有抽象类方法。

  3. 在类的构造函数中,使用Reflection创建InProcSessionStateStore类的实例(当为InProc配置时,ASP.NET使用该实例来存储会话状态-您的情况)将此实例存储在变量中

  4. 在所有重写的方法中使用InProc类的上述实例来执行必要的操作
  5. 在Web.Config中配置此新提供程序
  6. 最后但同样重要的是,实现日志记录

以下是示例代码(如果您需要一个包含更多信息的工作示例,还可以链接到其他人是如何创建自定义提供程序的)
https://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstatestoreproviderbase(v=vs.110).aspxhttp://www.codeproject.com/Articles/102000/ASP-NET-Custom-Session-Store-Provider-compatible-w

Web.Config

<sessionState mode="Custom" customProvider="custom_provider" ... >
      <providers>
        <add name="custom_provider" type="Xxxx.xxx.MySessionStateProvider"/>
      </providers>
</sessionState>

MySessionStateProvider类代码:

public class MySessionStateProvider : System.Web.SessionState.SessionStateStoreProviderBase {
    private readonly SessionStateStoreProviderBase InProcSessionStore;
    public MySessionStateProvider() {
        var inProcSessionStoreType = typeof(System.Web.SessionState.SessionStateStoreProviderBase).Assembly.GetType("System.Web.SessionState.InProcSessionStateStore");
        InProcSessionStore = (System.Web.SessionState.SessionStateStoreProviderBase)Activator.CreateInstance(inProcSessionStoreType);
        InProcSessionStore.Initialize(null, null);
    }
    public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) {
        return InProcSessionStore.CreateNewStoreData(context, timeout);
    }
    public override void CreateUninitializedItem(HttpContext context, string id, int timeout) {
        InProcSessionStore.CreateUninitializedItem(context, id, timeout);
    }
    public override void Dispose() {
        InProcSessionStore.Dispose();
    }
    //... Implement the rest of the method in the same manner.        
    public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) {
        return InProcSessionStore.SetItemExpireCallback(expireCallback);
    }
}