用.NET实现AOP框架
此后,将Director指导Builder组装的每个步骤通过 DirectorAttribute 属性类来表示,而Director在BuildUp的过程中,通过反射获得相关Builder的DirectorAttribute列表,对列表按照优先级排序后,执行每个DirectorAttribute指向的Build Part方法。
C#使用DirectorAttribute指导Builder的装配过程:
// 通过attribute 扩展Director
[AttributeUsage(AttributeTargets.Class, AllowMultiple =true)]
public sealed class DirectorAttribute : Attribute, IComparable<DirectorAttribute>
{
private int priority; // 执行优先级
private string method;
public DirectorAttribute(int priority, string method)
{
this.priority = priority;
this.method = method;
}
public int Priority { get { return this.priority; } }
public string Method { get { return this.method; } }
// 提供按照优先级比较的ICompare<T> 实现, 由于Array.Sort<T>
// 实际是升序排列,而Array.Reverse 是完全反转,因此这里调
// 整了比较的方式为“输入参数优先级- 当前实例优先级”
public int CompareTo(DirectorAttribute attribute)
{
return attribute.priority - this.priority;
}
}
public class Director
{
public void BuildUp(IAttributedBuilder builder)
{
// 获取Builder 的DirectorAttribute 属性
object[] attributes =
builder.GetType().GetCustomAttributes(typeof(DirectorAttribute), false);
if (attributes.Length <= 0) return;
DirectorAttribute[] directors = new DirectorAttribute[attributes.Length];
for (int i = 0; i < attributes.Length; i++)
directors[i] = (DirectorAttribute)attributes[i];
// 按每个DirectorAttribute 优先级逆序排序后,逐个执行
Array.Sort<DirectorAttribute>(directors);
foreach (DirectorAttribute attribute in directors)
InvokeBuildPartMethod(builder, attribute);
}
// helper method : 按照DirectorAttribute 的要求,执行相关的Builder 方法
private void InvokeBuildPartMethod(
IAttributedBuilder builder, DirectorAttribute attribute)
{
switch (attribute.Method)
{
case "BuildPartA": builder.BuildPartA(); break;
case "BuildPartB": builder.BuildPartB(); break;
case "BuildPartC": builder.BuildPartC(); break;
}
}
}
C#
[Director(1, "BuildPartB")]
[Director(2, "BuildPartA")]
public class AttributedBuilder : IAttributedBuilder
Unit Test
[TestMethod]
public void Test()
{
IAttributedBuilder builder = new AttributedBuilder();
Director director = new Director();
director.BuildUp(builder);
Assert.AreEqual<string>("a", builder.Log[0]);
Assert.AreEqual<string>("b", builder.Log[1]);
}
0
相关文章