如何在不改变下一个方面节点的旧值的情况下获得新值?

时间:2014-10-05 08:44:53

标签: c# postsharp aop

我有这种类型:

[NotifyPropertyChangedAspect]
public class MyDataModel
{
    ...
    [OnSetAspect("OnSelectedUserChanged")]
    public string SelectedUser { get; set; }
    ...
}

我应用这些方面:每班级方面:

[Serializable]
public class NotifyPropertyChangedAspect : LocationInterceptionAspect
{
    ...
    public override void OnSetValue(LocationInterceptionArgs args)
    {
        var newValue = args.Value;
        var oldValue = args.GetCurrentValue();
        args.ProceedSetValue();
        //base.OnSetValue(args); // same effect of ProceedSetValue()
        ... /* some more stuff... */ ...
    }
    ...
}

和每个字段方面:

[Serializable]
public class OnSetAspect : LocationInterceptionAspect
{
    ...
    public override void OnSetValue(LocationInterceptionArgs args)
    {
        var newValue = args.Value;
        var oldValue = args.GetCurrentValue();
        args.ProceedSetValue();
        //base.OnSetValue(args); // same effect of ProceedSetValue()
        ... /* some more stuff... */ ...
    }
    ...
}

现在发生的事情是NotifyPropertyChangedAspect.OnSetValue(...)被调用,当它调用args.GetCurrentValue()时,args.Value会更改其值(由于aspect绑定中的下一个节点,我猜)所以当调用OnSetAspect.OnSetValue(...)时,args.Value不再有效。

这两个方面都应该检查以前的值和新值(意味着即将设置的值)并做相应的事情。

它们不会改变要设置的值,所以它们不应该相互影响,但是它们会...

如何解开这两个方面?

1 个答案:

答案 0 :(得分:0)

这里的误解是,当您在类上指定aspect属性时,它不会应用于该类,而是在该类上进行多播。多播是一种机制,它将属性(不是方面!)递归地应用于所有包含的声明,甚至是派生的声明。请参阅PostSharp documentation on this matter

真正应用方面的声明是与方面级别匹配的声明。有以下基本方面级别:

  • AssemblyLevelAspect
  • TypeLevelAspect
  • InstanceLevelAspect
  • MethodLevelAspect
  • LocationLevelAspect
  • FieldLevelAspect
  • EventLevelAspect

Aspect的运行时实例然后每个实体存在一次。即在您的情况下,每个位置都有一个单例方面实例。

在你的情况下,你将一个LocationLevelAspect应用于一个类,这使得方面在所有字段上被多播,因此你最终在每个字段/属性上都有两个LocationInterceptionAspects。

args.GetCurrentValue()获取基础属性的值,但不应更改args.Value,它与属性设置器中的value参数具有相同的语义。

因此,方面并没有真正纠结,它们按顺序应用(您可以指定)。并且始终完全包装前一个。