面向方面设计模式使用PostSharp在C#中使用Cuckoo's Egg

时间:2013-11-22 16:07:10

标签: c# design-patterns postsharp aop

我正在尝试使用 Postsharp 在C#中实现AO设计模式Cuckoo的蛋。

这种设计模式的概念就像它的名称状态一样,用其他对象替换现有对象。在 AspectJ 中,它由以下内容完成:

public aspect MyClassSwapper {
  public pointcut myConstructors(): call(MyClass.new());
  Object around(): myConstructors() {
      return new AnotherClass();
  }
}

public class AnotherClass extends MyClass {
    . . .
}

我是Postsharp的新手所以我想问一下,如果Postsharp中有工具可以做类似的事情 - 覆盖基类构造函数的返回值并返回子类的对象?

1 个答案:

答案 0 :(得分:0)

虽然 PostSharp 允许您将OnMethodBoundaryAspect应用于构造函数,但您仍然无法替换返回的对象实例。实际上,C#中的构造函数不返回值。相关问题herehere

实现Cuckoo的egg模式的另一种方法是拦截原始类的方法,而是在另一个类实例上调用适当的方法。在这种情况下,AnotherClass甚至不必从MyClass派生,或者您可以将不同的方法委托给不同的替换类。

实现模式的MethodInterceptionAspect的示例实现如下所示:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, Inheritance = MulticastInheritance.None)]
public class MyClassSwapperAttribute : MethodInterceptionAspect, IInstanceScopedAspect
{
    private readonly Type cuckooType;

    [NonSerialized] private object cuckooEgg;

    public MyClassSwapperAttribute(Type cuckooType)
    {
        this.cuckooType = cuckooType;
    }

    private MyClassSwapperAttribute()
    {
        // this creates an "empty" aspect instance applied on the cuckoo's egg itself
    }

    public object CreateInstance(AdviceArgs adviceArgs)
    {
        if (adviceArgs.Instance.GetType() == cuckooType)
            return new MyClassSwapperAttribute();

        return this.MemberwiseClone();
    }

    public void RuntimeInitializeInstance()
    {
        if (this.cuckooType == null)
            return;

        // for each instance of the target class we create a new cuckoo's egg instance
        this.cuckooEgg = Activator.CreateInstance(cuckooType);
    }

    public override void OnInvoke(MethodInterceptionArgs args)
    {
        if (this.cuckooEgg == null)
        {
            base.OnInvoke(args);
        }
        else
        {
            // delegate the method invocation to the cuckoo's egg, that derives from the target class
            args.ReturnValue = args.Method.Invoke(this.cuckooEgg, args.Arguments.ToArray());
        }
    }
}

此实现需要AnotherClassMyClass派生,您必须在MyClass本身上应用该属性,例如:

[MyClassSwapper(typeof (AnotherClass))]
class MyClass
{
    // ...
}