AOP:使用命令模式实现AOP
原帖地址:http://www.cnblogs.com/happyframework/archive/2013/06/06/3120410.html
背景
某位大牛说过,采用命名模式的好处是,你可以将命令按照不同的方式执行,如:排队、异步、远程和拦截等等。今天我介绍一下如何拦截命令的执行,这有些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 /// <summary>
10 /// 命令接口。
11 /// </summary>
12 public interface ICommand
13 {
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 /// <summary>
10 /// 命令处理器接口,一个命令只能有一个命令处理器。
11 /// </summary>
12 public interface ICommandHandler<TCommand>
13 where TCommand : ICommand
14 {
15 /// <summary>
16 /// 处理命令。
17 /// </summary>
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 /// <summary>
10 /// 命令执行上下文接口,代表了一次命令的执行过程。
11 /// </summary>
12 public interface ICommandExecuteContext
13 {
14 /// <summary>
15 /// 命令执行服务。
16 /// </summary>
17 ICommandService CommandService { get; }
18
19 /// <summary>
20 /// 正在执行的命令。
21 /// </summary>
22 ICommand Command { get; }
23
24 /// <summary>
25 /// 执行下一个<see cref="CommandInterceptorAttribute"/>,如果已经是最后一个,就会执行<see cref="ICommandHandler{TCommand}"/>。
26 /// </summary>
27 void ExecuteNext();
28 }
29 }
命令拦截器,拦截正在被执行的命令。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Happy.Command
{
/// <summary>
/// 命令拦截器,拦截正在被执行的命令。
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public abstract class CommandInterceptorAttribute : Attribute
{
/// <summary>
/// 构造方法。
/// </summary>
/// <param name="order">指示拦截器在管道中的位置</param>
protected CommandInterceptorAttribute(int order)
{
this.Order = order;
}
/// <summary>
/// 拦截正在被执行的命令。
/// </summary>
/// <param name="context">命令执行上下文</param>
public abstract void Intercept(ICommandExecuteContext context);
/// <summary>
/// 拦截器在管道中的位置。
/// </summary>
public int Order { get; protected set; }
}
}
管道过滤器的内部实现
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 CommandInterceptorChain
10 {
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 CurrentCommandInterceptor
27 {
28 get
29 {
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 else
43 {
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.Transactions;
7
8 namespace Happy.Command
9 {
10 /// <summary>
11 /// 事务拦截器。
12 /// </summary>
13 public sealed class TransactionAttribute : CommandInterceptorAttribute
14 {
15 /// <inheritdoc />
16 public TransactionAttribute(int order) : base(order) { }
17
18 /// <inheritdoc />
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.Application
12 {
13 /// <summary>
14 /// 简单的创建命令。
15 /// </summary>
16 [Transaction(1)]
17 public abstract class SimpleCreateCommand<TAggregateRoot> : SimpleCommand<TAggregateRoot>
18 where TAggregateRoot : AggregateRoot
19 {
20 }
21 }
执行命令
1 /// <summary>
2 /// 创建。
3 /// </summary>
4 public ActionResult Create(TAggregateRoot item)
5 {
6 this.CurrentCommandService.Execute(new TCreateCommand
7 {
8 Aggregate = item
9 });
10
11 return this.NewtonsoftJson(new
12 {
13 success = true,
14 items = this.GetById(item.Id)
15 });
16 }
备注
这里的命令模式本质上是一种消息模式,因为命令里没有任何行为,将行为独立了出来。像WCF、ASP.NET和ASP.NET MVC本质上也是消息模式,他们也内置了管道过滤器模式。