博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AOP:使用命令模式实现AOP
阅读量:4564 次
发布时间:2019-06-08

本文共 8469 字,大约阅读时间需要 28 分钟。

背景

某位大牛说过,采用命名模式的好处是,你可以将命令按照不同的方式执行,如:排队、异步、远程和拦截等等。今天我介绍一下如何拦截命令的执行,这有些AOP的味道。

思路

就是一个管道过滤器而已

实现

先不考虑处理器的实例化和过滤器列表的实例化,如果给你一个命令、一些过滤器和一个处理器,让你组装为一个管道应该不是啥大问题。

这部分概念虽然简单,可是也不见得好理解,因此我基本把全部代码都贴上了,建议不太明白的同学,自己重写一遍,加深对管道过滤器的理解。

核心代码

命令接口

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Command 8 { 9     /// 10     /// 命令接口。11     /// 12     public interface ICommand13     {14     }15 }

命令处理器接口,一个命令只能有一个命令处理器。

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Command 8 { 9     /// 10     /// 命令处理器接口,一个命令只能有一个命令处理器。11     /// 12     public interface ICommandHandler
13 where TCommand : ICommand14 {15 ///
16 /// 处理命令。17 /// 18 void Handle(TCommand command);19 }20 }

命令拦截器,拦截正在被执行的命令。

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Command 8 { 9     /// 10     /// 命令拦截器,拦截正在被执行的命令。11     /// 12     [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]13     public abstract class CommandInterceptorAttribute : Attribute14     {15         /// 16         /// 构造方法。17         /// 18         /// 指示拦截器在管道中的位置19         protected CommandInterceptorAttribute(int order)20         {21             this.Order = order;22         }23 24         /// 25         /// 拦截正在被执行的命令。26         /// 27         /// 命令执行上下文28         public abstract void Intercept(ICommandExecuteContext context);29 30         /// 31         /// 拦截器在管道中的位置。32         /// 33         public int Order { get; protected set; }34     }35 }

命令执行上下文接口,代表了一次命令的执行过程。

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Command 8 { 9     /// 10     /// 命令执行上下文接口,代表了一次命令的执行过程。11     /// 12     public interface ICommandExecuteContext13     {14         /// 15         /// 命令执行服务。16         /// 17         ICommandService CommandService { get; }18 19         /// 20         /// 正在执行的命令。21         /// 22         ICommand Command { get; }23 24         /// 25         /// 执行下一个
,如果已经是最后一个,就会执行
。26 ///
27 void ExecuteNext();28 }29 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 using Happy.ExtensionMethod.Reflection; 8  9 namespace Happy.Command.Internal10 {11     internal sealed class CommandExecuteContext : ICommandExecuteContext12     {13         private CommandInterceptorChain _commandInterceptorChain;14 15         internal CommandExecuteContext(ICommandService commandService, ICommand command, Action commandExecutor)16         {17             this.CommandService = commandService;18             this.Command = command;19             _commandInterceptorChain = new CommandInterceptorChain(20                 this,21                 command.GetType().GetAttributes
(),22 commandExecutor);23 }24 25 26 public ICommandService CommandService27 {28 get;29 private set;30 }31 32 public ICommand Command { get; private set; }33 34 public void ExecuteNext()35 {36 _commandInterceptorChain.ExecuteNext();37 }38 }39 }

管道过滤器的内部实现

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace Happy.Command.Internal 8 { 9     internal sealed class CommandInterceptorChain10     {11         private ICommandExecuteContext _commandExecuteContext;12         private CommandInterceptorAttribute[] _commandInterceptors;13         private Action _commandExecutor;14         private int _currentCommandInterceptorIndex = -1;15 16         internal CommandInterceptorChain(17             ICommandExecuteContext commandExecuteContext,18             CommandInterceptorAttribute[] commandInterceptors,19             Action commandExecutor)20         {21             _commandExecuteContext = commandExecuteContext;22             _commandInterceptors = commandInterceptors.OrderBy(x => x.Order).ToArray();23             _commandExecutor = commandExecutor;24         }25 26         private CommandInterceptorAttribute CurrentCommandInterceptor27         {28             get29             {30                 return _commandInterceptors[_currentCommandInterceptorIndex];31             }32         }33 34         internal void ExecuteNext()35         {36             _currentCommandInterceptorIndex++;37 38             if (_currentCommandInterceptorIndex < _commandInterceptors.Length)39             {40                 this.CurrentCommandInterceptor.Intercept(_commandExecuteContext );41             }42             else43             {44                 _commandExecutor();45             }46         }47     }48 }

命令服务,负责执行命令

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Threading; 7  8 using Common.Logging; 9 using Microsoft.Practices.ServiceLocation;10 11 using Happy.DesignByContract;12 13 namespace Happy.Command.Internal14 {15     internal sealed class DefaultCommandService : ICommandService16     {17         private readonly Dictionary
_services = new Dictionary
();18 19 public void Execute
(TCommand command)20 where TCommand : ICommand21 {22 command.MustNotNull("command");23 24 var context = this.CreateCommandExecuteContext(command);25 26 context.ExecuteNext();27 }28 29 public ICommandService AddService
(T service)30 {31 _services[typeof(T)] = service;32 33 return this;34 }35 36 public T GetService
()37 {38 return (T)_services[typeof(T)];39 }40 41 private CommandExecuteContext CreateCommandExecuteContext
(TCommand command)42 where TCommand : ICommand43 {44 45 return new CommandExecuteContext(this, command, () =>46 {47 this.ExecuteCommandHandler(command);48 });49 }50 51 private void ExecuteCommandHandler
(TCommand command)52 where TCommand : ICommand53 {54 ServiceLocator.Current.MustNotNull("ServiceLocator.Current");55 56 var commandHandler = ServiceLocator57 .Current58 .GetInstance
>();59 60 commandHandler.Handle(command);61 }62 }63 }

事务拦截器

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Transactions; 7  8 namespace Happy.Command 9 {10     /// 11     /// 事务拦截器。12     /// 13     public sealed class TransactionAttribute : CommandInterceptorAttribute14     {15         /// 
16 public TransactionAttribute(int order) : base(order) { }17 18 ///
19 public override void Intercept(ICommandExecuteContext context)20 {21 using (var ts = new TransactionScope())22 {23 context.ExecuteNext();24 25 ts.Complete();26 }27 }28 }29 }

应用事务拦截器

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 using Happy.Domain; 8 using Happy.Command; 9 using Happy.DesignByContract;10 11 namespace Happy.Application12 {13     /// 14     /// 简单的创建命令。15     /// 16     [Transaction(1)]17     public abstract class SimpleCreateCommand
: SimpleCommand
18 where TAggregateRoot : AggregateRoot19 {20 }21 }

执行命令

1         ///  2         /// 创建。 3         ///  4         public ActionResult Create(TAggregateRoot item) 5         { 6             this.CurrentCommandService.Execute(new TCreateCommand 7             { 8                 Aggregate = item 9             });10 11             return this.NewtonsoftJson(new12             {13                 success = true,14                 items = this.GetById(item.Id)15             });16         }

备注

这里的命令模式本质上是一种消息模式,因为命令里没有任何行为,将行为独立了出来。像WCF、ASP.NET和ASP.NET MVC本质上也是消息模式,他们也内置了管道过滤器模式。

 

转载于:https://www.cnblogs.com/happyframework/archive/2013/06/06/3120410.html

你可能感兴趣的文章
构建之法阅读笔记之四
查看>>
10.15习题2
查看>>
Windows Server 2008 R2 备份与恢复详细实例
查看>>
Ubuntu上kubeadm安装Kubernetes集群
查看>>
关于java学习中的一些易错点(基础篇)
查看>>
MFC的多国语言界面的实现
查看>>
四则运算个人项目 最终版
查看>>
java线程系列---java5中的线程池
查看>>
SQL表连接
查看>>
新秀系列C/C++经典问题(四)
查看>>
memset函数具体说明
查看>>
经常使用的android弹出对话框
查看>>
确保新站自身站点设计的合理性的六大注意点
查看>>
promise
查看>>
Go 网络编程笔记
查看>>
[]Java面试题123道
查看>>
中间件与auth认证的那点儿所以然
查看>>
Scala
查看>>
Android 中LinearLayout控件属性
查看>>
面向对象之多态性
查看>>