前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Context+ContextScope——这是否可以看作一种设计模式?

Context+ContextScope——这是否可以看作一种设计模式?

作者头像
蒋金楠
发布于 2022-05-09 05:06:06
发布于 2022-05-09 05:06:06
17700
代码可运行
举报
文章被收录于专栏:大内老A大内老A
运行总次数:0
代码可运行

相信大家对TransactionScope都比较熟悉。通过TransactionScope,我们可以很容易地将一组操作纳入同一个事务中;或者说TransactionScope创建一个基于事务的上下文范围,在这个范围内共享一个相同的环境事务(Ambient Transaction)。我个人觉得这体现了一种可以重用的模式,即本篇文章介绍的Context+ContextScope模式,这种模式旨在一定范围内创建一个可以共享的上下文信息。

我们通过一个简单的例子来对Context+ContextScope模式进行简单说明。比如在一个安全级别比较高的GUI应用中,我们需要对用户的每一个UI操作进行安全审核(Auditing,比如记录下当前操作的意图、操作时间和用户名等),我们将这个被审核的UI操作称为“活动(Activity)”。如果我们能够将针对这个UI操作的执行(事件的触发、对业务逻辑的执行以及对数据库的访问)纳入同一个基于活动的上下文中,那么审核就可以直接从当前的环境上下文中获取到相应的审核信息了。[源代码从这里下载]

一、ActivityContext

为此,我们创建了如下一个名为ActivityContext的类型表示针对Activity的上下文。ActivityContext具有三个实例属性,其中ActivityName和DateTime表示活动的名称和开始时间,而字典类型的Properties 属性用于维护Activity相关的额外属性。静态Current属性表示当前的环境上下文(Ambient Context),它返回的是静态字段current。值得一提的,在该静态字段上应用了ThreadStaticAttribute特性,意味着静态字段仅仅限于当前的线程。这也说明了Context+ContextScope模式主要应用于同步环境,如果需要对异步环境进行支持,可以做一些额外处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1: public class ActivityContext: IDisposable

       2: {

       3:     [ThreadStatic]

       4:     private static ActivityContext current;

       5:  

       6:     public string ActivityName { get; private set; }

       7:     public DateTime StartTime { get; private set; }

       8:     public IDictionary<string, object> Properties { get; private set; }

       9:  

      10:     internal ActivityContext(string activityName)

      11:     {

      12:         this.ActivityName = activityName;

      13:         this.StartTime = DateTime.Now;

      14:         this.Properties = new Dictionary<string, object>();

      15:     }

      16:  

      17:     public static ActivityContext Current

      18:     {

      19:         get { return current; }

      20:         internal set{current = value;}

      21:     }

      22:  

      23:     public void Dispose()

      24:     {

      25:         foreach (var property in this.Properties.Values)

      26:         {

      27:             IDisposable disposable = property as IDisposable;

      28:             if (null != disposable)

      29:             {

      30:                 disposable.Dispose();

      31:             }

      32:         }

      33:     }

      34: }

二、ActivityContextScope

Context+ContextScope的核心不在于Context而在于ContextScope,即我们需要控制上下文的范围。对于我们的安全审核场景来说,我们需要针对用于的UI操作(比如点击某个按钮)创建ActivityContext,该上下文的生命周期仅限于针对UI事件的响应过程。为此我们创建一个ActivityContextScope类型用于创建ActivityContext并控制其生命周期。如下面的代码片断所示,ActivityContextScope除了接受一个表示创建活动的名称之外,还具有一个ContextScopeOperation枚举类型的参数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1: public class ActivityContextScope: IDisposable

       2: {

       3:     private ActivityContext current = ActivityContext.Current;

       4:     private ActivityContext newContext;

       5:  

       6:     public ActivityContextScope(string activityName, ContextScopeOption contextScopeOption = ContextScopeOption.Required)

       7:     {

       8:         switch (contextScopeOption)

       9:         {

      10:             case ContextScopeOption.Required:

      11:                 {

      12:                     if (null == current)

      13:                     {

      14:                         ActivityContext.Current = newContext = new ActivityContext(activityName);

      15:                     }

      16:                     break;

      17:                 }

      18:             case ContextScopeOption.RequiresNew:

      19:                 {

      20:                     ActivityContext.Current = newContext = new ActivityContext(activityName);

      21:                     break;

      22:                 }

      23:             case ContextScopeOption.Suppress:

      24:                 {

      25:                     ActivityContext.Current = null;

      26:                     break;

      27:                 }

      28:         }

      29:     }

      30:  

      31:     public void Dispose()

      32:     {

      33:         ActivityContext.Current = current;

      34:         if (null != newContext)

      35:         {

      36:             newContext.Dispose();

      37:         }

      38:     }

      39: }

      40:  

      41: public enum ContextScopeOption

      42: {

      43:     Required,

      44:     RequiresNew,

      45:     Suppress

      46: }

考虑在创建ActivityContextScope的时候,当前环境上下文可能已经存在,那么是重用现成的上下文还是创建新的上下文,可以通过ContextScopeOperation枚举来控制。该枚举类型的Required和RequiredNew选项分别表示重用现有上下文和创建新的上下文。另一个选项Supress表示创建一个“无环境上下文”的范围,比如TransactionScope通过类似的机制将不需要纳入事务的操作(比如Logging)从环境事务中剥离出来。基于ContextScopeOperation的ActivityContext创建机制体现在ActivityContextScope的构造函数中。ActivityContextScope实现了IDisposable接口,在实现的Dispose方法中我们将通过ActivityContext的静态属性Current表示的环境上下文恢复到ActivityContextScope创建之前的状态。

三、ActivityContextScope的使用

我们通过如下一个简单的实例来演示ActivityContextScope的使用。在Main方法中我们在一个基于“Activty1”的ActivityContextScope中调用Activty1方法。在Activty1方法中,我们在一个基于“Activty2”的ActivityContextScope中调用Activty2方法。两次创建ActivityContextScope都采用默认的ContextScopeOperation(Required)。在方法Activty2中,我们在一个基于“Activty3”的ActivityContextScope中调用Activty3方法,创建ActivityContextScope时选择RequiredNew选项。而在Activty3方法中,我们针对Supress选项创建ActivityContextScope并调用Activity4方法。方法Activty1、Activty2、Activty3和Activty4中均调用DisplayCurrentContext将当前的ActivityContext信息打印出来。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1: class Program

       2: {

       3:     static void Main(string[] args)

       4:     {

       5:         using (ActivityContextScope contextScope = new ActivityContextScope("Activty1"))

       6:         {

       7:             Activty1();

       8:         }

       9:     }

      10:  

      11:     static void DisplayCurrentContext(string methodName)

      12:     {

      13:         if (null != ActivityContext.Current)

      14:         {

      15:             Console.WriteLine("{0}: Current ambient activity is {1}", methodName, ActivityContext.Current.ActivityName);

      16:         }

      17:         else

      18:         {

      19:             Console.WriteLine("{0}: No ambient activity.", methodName);

      20:         }

      21:     }

      22:  

      23:     private static void Activty1()

      24:     {

      25:         DisplayCurrentContext("Activty1");

      26:         using (ActivityContextScope contextScope = new ActivityContextScope("Activty2"))

      27:         {

      28:             Activty2();

      29:         }

      30:     }

      31:  

      32:     private static void Activty2()

      33:     {

      34:         DisplayCurrentContext("Activty2");

      35:         using (ActivityContextScope contextScope = new ActivityContextScope("Activty3", ContextScopeOption.RequiresNew))

      36:         {

      37:             Activty3();

      38:         }

      39:     }

      40:  

      41:     private static void Activty3()

      42:     {

      43:         DisplayCurrentContext("Activty3");

      44:         using (ActivityContextScope contextScope = new ActivityContextScope("", ContextScopeOption.Suppress))

      45:         {

      46:             Activty4();

      47:         }

      48:     }

      49:  

      50:     private static void Activty4()

      51:     {

      52:         DisplayCurrentContext("Activty4");

      53:     }

      54: }

上面这段程序执行之后会在控制台上生成如下的输出结果,我们可以看到当前环境上下文是严格按照我们创建ActivityContextScope的方式来控制的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1: Activty1: Current ambient activity is Activty1

       2: Activty2: Current ambient activity is Activty1

       3: Activty3: Current ambient activity is Activty3

       4: Activty4: No ambient activity.
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
通过扩展改善ASP.NET MVC的验证机制[实现篇]
在《使用篇》中我们谈到扩展的验证编程方式,并且演示了本解决方案的三大特性:消息提供机制的分离、多语言的支持和多验证规则的支持,我们现在来看看这样的验证解决方案最终是如何实现的。 目录: 一、为验证创建一个上下文:ValidatorContext 二、通过自定义ActionInvoker在进行操作执行之前初始化上下文 三、为Validator创建基类:ValidatorBaseAttribute 四、通过自定义ModelValidatorProvider
蒋金楠
2018/01/15
7940
以上下文(Context)的形式创建一个共享数据的容器
在很多情况下我们具有这样的需求:为一组相关的操作创建一个执行上下文并提供一个共享的数据容器,而不是简单地定义一个全局变量,或者将数据通过参数传来传去。这样的上下文一般具有其生命周期,它们在目标操作开始执行的时候被激活,在执行完成之后被回收。该上下文一般不能跨越多个线程,以避免多个线程操作相同的数据容器造成数据的不一致。针对这个需求,我们写了一个非常简单的例子,有兴趣的朋友可以看看。[源代码从这里下载] 目录 一、ExecutionContext的基本编程方式 二、异步调用的问题
蒋金楠
2018/01/15
6090
谈谈分布式事务之三: System.Transactions事务详解[下篇]
在前面一篇给出的Transaction的定义中,信息的读者应该看到了一个叫做DepedentClone的方法。该方法对用于创建基于现有Transaction对象的“依赖事务(DependentTransaction)”。不像可提交事务是一个独立的事务对象,依赖事务依附于现有的某个事务(可能是可提交事务,也可能是依赖事务)。依赖事务可以帮助我们很容易地编写一些事务型操作,当环境事务不存的时候,可以确保操作在一个独立的事务中执行;当环境事务存在的时候,则自动加入其中。 一、依赖事务(Dependent Tra
蒋金楠
2018/01/16
1.1K0
谈谈分布式事务之三: System.Transactions事务详解[下篇]
TransactionScope使用说明
参考MSDN :http://msdn.microsoft.com/zh-cn/library/system.transactions.transactionscope.aspx
全栈程序员站长
2022/09/09
6720
TransactionScope事务处理方法介绍及.NET Core中的注意事项
今天在写CzarCms的UnitOfWork的使用使用到了这个TransactionScope事务,因此对它进行了相关资料的查阅并记录如下,希望对大伙在.NET Core中使用有所帮助。
依乐祝
2018/12/28
1.7K0
一个简易版的T4代码生成"框架"
对于企业开发来说,代码生成在某种意义上可以极大地提高开发效率和质量。在众多代码生成方案来说,T4是一个不错的选择,今天花了点时间写了一个简易版本的T4代码生成的“框架”,该框架仅仅是定义了一些基本的基类以及其他与VS集成相关功能的类型而已。[源代码从这里下载] 目录 一、T4模版的定义和代码文件的生成 二、TransformationContext与TransformationContextScope 三、Template 四、Generator
蒋金楠
2018/01/15
7170
一个简易版的T4代码生成"框架"
.NET面向上下文、AOP架构模式(实现)
在本人的.NET面向上下文、AOP架构模式(概述)一文中,我们大概了解了上下文如何辅助对象在运行时的管理。在很多时候我们急需在运行时能把对象控制在一定的逻辑范围内,在必要的时候能让他们体现出集中化的概念,如人群、车辆、动物等等。而Context与AOP有着密切的联系,Context表示逻辑抽象的范围而AOP描述了在这个逻辑范围内如何进行控制。其实这两者都是设计模式外的设计模式,与具体的技术实现无关。[王清培版权所有,转载请给出署名]
王清培
2019/03/01
7140
.NET面向上下文、AOP架构模式(实现)
诊断日志知多少 | DiagnosticSource 在.NET上的应用
最近为了解决ABP集成CAP时无法通过拦截器启用工作单元的问题,从小伙伴那里学了一招。借助DiagnossticSource,可以最小改动完成需求。关于DiagnosticSource晓东大佬18年在文章 在 .NET Core 中使用 Diagnostics (Diagnostic Source) 记录跟踪信息就有介绍,文章开头就说明了Diagnostics 一直是一个被大多数开发者忽视的东西。是的,我也忽略了,这个好东西,有必要学习一下,下面就和大家简单聊一聊System.Diagnostics.DiagnosticSource在.NET上的应用。
圣杰
2020/10/16
1K0
诊断日志知多少 | DiagnosticSource 在.NET上的应用
详细讲解23种设计模式
工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法把对象的实例化推迟到子类。
tokengo
2023/03/01
9000
设计模式学习笔记(二十)状态模式及其实现
状态模式(State Pattern)指允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
归思君
2023/10/16
6400
设计模式学习笔记(二十)状态模式及其实现
WCF技术剖析之十七:消息(Message)详解(下篇)
《WCF技术剖析(卷1)》自出版近20天以来,得到了园子里的朋友和广大WCF爱好者的一致好评,并被卓越网计算机书店作为首页推荐,在这里对大家的支持表示感谢。同时我将一直坚持这个博文系列,与大家分享我对WCF一些感悟和学习经验。在《消息(Message)详解》系列的上篇和中篇,先后对消息版本、详细创建、状态机和基于消息的基本操作(读取、写入、拷贝、关闭)进行了深入剖析,接下来我们来谈谈消息的另一个重要组成部分:消息报头(Message Header)。 按照SOAP1.1或者SOAP1.2规范,一个SOAP消
蒋金楠
2018/01/16
1.2K0
WCF技术剖析之十七:消息(Message)详解(下篇)
设计模式-状态模式
最近项目中有个项目是用到了状态得操作,比如从审核到审核通过再到审核查看审核中再到审核完成等一系列得状态。
技术从心
2020/11/06
4390
谈谈分布式事务之三: System.Transactions事务详解[上篇]
在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务。.NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集中的System.Transactions命名空间下,我们直接称基于此的事务为System.Transactions事务。System.Transactions事务编程模型使我们可以显式(通过System.Transactions.Transaction)或者隐式(基于System.Transactions.T
蒋金楠
2018/01/16
1.5K0
.NET 8 依赖注入
依赖注入(Dependency Injection,简称DI)是一种设计模式,用于解耦组件(服务)之间的依赖关系。它通过将依赖关系的创建和管理交给外部容器来实现,而不是在组件(服务)内部直接创建依赖对象。
郑子铭
2023/12/15
3830
.NET 8 依赖注入
C# 从代码入门 Mysql 数据库事务
在业务开发中,使用数据库事务是必不可少的。而开发中往往会使用各种 ORM 执行数据库操作,简化代码复杂度,不过,由于各种 ORM 的封装特性,开发者的使用方式也不一样,开发者想要了解 ORM 对事务做了什么处理是比较难的。因此,本文介绍数据库事务基础、Ado.net 事务、如何封装 DbContext ,读者掌握以后,可以加深对 C# 使用事务的理解,使用各种 ORM 时也会更应手。
痴者工良
2023/12/14
3450
C# 从代码入门 Mysql 数据库事务
Context到底是个啥?
该类包括了一个真正的Context对象,也就是ContextImpl。其是ContextImpl的代理模式。
我就是马云飞
2018/08/02
4560
VSCode 源码解读:事件系统设计
最近在研究前端大型项目中要怎么管理满天飞的事件、模块间各种显示和隐式调用的问题,本文结合相应的源码分析,记录 VS Code 中的事件管理系统设计。
被删
2024/07/23
5384
VSCode 源码解读:事件系统设计
.Net中的5种事务总结
在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了。因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种事务处理的方法。大家可以参考一下,根据实际选择适当的事务处理。 1、SQL事务     sql事务是使用SQL server自身的事务:在存储过程中直接使用Begin Tran,Rollback Tran,Commit Tran实现事务: 优点:执行效率最佳 限制:事务上下文仅在数据库中调用,难以实现复杂的业务
跟着阿笨一起玩NET
2018/09/18
5460
23种设计模式(七)-状态设计模式
通常对有状态的对象进行编程,我们的解决方案是:思考可能存在的所有状态,然后使用 if-else 或 switch-case 语句来进行状态判断,然后再根据不同的状态进行不同的处理。如上面的案例--淘宝下单:
用户7798898
2021/07/13
1.2K0
设计模式学习(二): 观察者模式 (C#)
《深入浅出设计模式》学习笔记第二章 需求: 开发一套气象监测应用,如图: 气象站,目前有三种装置,温度、湿度和气压感应装置。 WeatherData对象追踪气象站的数据,并更新到布告板,布告板(目前是
solenovex
2018/03/01
7430
设计模式学习(二): 观察者模式 (C#)
推荐阅读
相关推荐
通过扩展改善ASP.NET MVC的验证机制[实现篇]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验