C# 寻求“一刀切”的基于上下文的存储

C# 寻求“一刀切”的基于上下文的存储,c#,.net,httpcontext,thread-static,C#,.net,Httpcontext,Thread Static,首先,我希望基于上下文的存储在整个框架中保持一致 话虽如此,我正在寻找一个优雅的解决方案,使这些属性在ASP.NET、WCF和任何其他多线程.NET代码中都是安全的。这些属性位于一些低级跟踪帮助程序中(如果您想知道为什么它们是内部的,可以通过方法公开) 我不希望依赖于不需要的程序集(如System.Web等)。我不想要求任何使用此代码的人配置任何东西。我只是想让它工作;)但这可能太高了 有人有什么窍门吗?(我看过Spring的实现) 内部静态字符串CurrentInstance { 得到 { 以

首先,我希望基于上下文的存储在整个框架中保持一致

话虽如此,我正在寻找一个优雅的解决方案,使这些属性在ASP.NET、WCF和任何其他多线程.NET代码中都是安全的。这些属性位于一些低级跟踪帮助程序中(如果您想知道为什么它们是内部的,可以通过方法公开)

我不希望依赖于不需要的程序集(如System.Web等)。我不想要求任何使用此代码的人配置任何东西。我只是想让它工作;)但这可能太高了

有人有什么窍门吗?(我看过Spring的实现)

内部静态字符串CurrentInstance
{
得到
{
以字符串形式返回CallContext.LogicalGetData(currentInstanceSlotName);
}
设置
{
LogicalSetData(currentInstanceSlotName,值);
}
}

内部静态堆栈

如果只是为了提供对属性的线程安全访问,我不知道在这里使用CallContext是正确的选择。如果是这样,lock语句就是您所需要的全部

但是,您必须确保正确应用它

使用CallContext,您将获得线程安全访问,因为当调用来自不同线程(或者不同存储区)时,您将拥有CallContext的单独实例。然而,这与使对资源线程的访问变得安全是非常不同的

如果您想在多个线程之间共享相同的值,那么lock语句就是最好的选择。否则,如果您希望在每个线程/调用的基础上使用特定值,请使用CallContext,或在thread类上使用静态GetData/SetData方法,或ThreadStatic属性(或任何数量的基于线程的存储机制)。

以下是指向NHibernate的“上下文”实现的链接(至少是其中的一部分):

我不清楚这在NHibernate的环境中究竟在哪里或如何发挥作用。也就是说,如果我想在“上下文”中存储一些值,我会从NHibernate获取“上下文”并添加我的值吗?我不使用NHibernate,所以我真的不知道

我想您可以自己查看并确定这种实现是否对您有用。显然,这个想法是注入所需的实现,具体取决于应用程序的类型(ASP.NET、WCF等)。这可能意味着一些配置(如果使用MEF加载“ICurrentSessionContext”接口,则可能是最小配置)

不管怎么说,我发现这个想法很有趣,因为不久前我在搜索
CallContext.SetData/GetData/LogicalSetData/LogicalGetData
Thread.SetData/GetData
[ThreadStatic]
等信息时发现了它

另外,基于您使用的是
CallContext.LogicalSetData
而不是
CallContext.SetData
,我假设您希望利用这样一个事实,即与逻辑线程关联的信息将传播到子线程,而不只是希望有一个“线程安全”的位置来存储信息。因此,如果要在应用程序启动时设置(pr Push)环境活动,然后不推送任何其他活动,则任何后续线程也将是该活动的一部分,因为通过LogicalSetData存储的数据由子线程继承

如果你从第一次问这个问题起就学到了什么,我很想听听。即使你没有,我也会有兴趣了解你在上下文中所做的事情

目前,我正在为日志/跟踪维护一些上下文信息(类似于Trace.CorrelationManager.ActivityId和Trace.CorrelationManager.LogicalOpertionStack以及log4net/NLog上下文支持)。我想保存一些上下文(当前应用程序、当前应用程序实例、当前活动(可能是嵌套的))以便在应用程序或WCF服务中使用,我想跨WCF服务边界“自动”传播它。这是为了允许记录在中央存储库中的日志记录语句通过客户端/活动/等进行关联。我们将能够通过特定应用程序的特定实例查询和关联所有日志记录语句。日志记录语句可能已在客户端或一个或多个WCF服务中生成

ActivityId的WCF传播对我们来说并不一定足够,因为我们想要传播(或者我们认为我们需要传播)的不仅仅是ActivityId。此外,我们希望将此信息从Silverlight客户端传播到WCF服务,并且Trace.CorrelationManager在Silverlight中不可用(至少在4.0中不可用,将来可能会提供类似的功能)

目前,我正在使用IClientMessageInspector和IDispatchMessageInspector原型化“上下文”信息的传播。看来这对我们来说很可能行得通


关于对System.Web的依赖关系,NHibernate实现确实有一个“ReflectiveHttpContext”,它使用反射来访问HttpContext,因此不会有对System.Web的项目依赖关系。显然,如果配置为使用HttpContext,部署应用程序的地方必须有System.Web。

我不关心同步。正如你所说,它们有许多基于上下文的存储机制,有些机制在某些情况下不起作用(如ASP.NET中的CallContext和ThreadStatic),因此我提出了这个问题。我没有太多可以提供的,但我也对这个问题感兴趣。FWIW我记得在一些源代码库(可能是Castle、NInject或NHibernate)中看到了一些类似IContext的实现,我猜这些实现都是为了将其导入到应用程序中。每个IContext实现都使用不同的技术(CallContext、HttpContext、Thread.SetData等)。我不知道到底是怎么回事
    internal static string CurrentInstance
    {
        get
        {
            return CallContext.LogicalGetData(currentInstanceSlotName) as string;
        }
        set
        {
            CallContext.LogicalSetData(currentInstanceSlotName, value);
        }
    }

    internal static Stack<ActivityState> AmbientActivityId
    {
        get
        {
            Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>;
            if (stack == null)
            {
                stack = new Stack<ActivityState>();
                CallContext.LogicalSetData(ambientActivityStateSlotName, stack);
            }

            return stack;
        }
    }