如何动态应用方面

本文关键字:应用 方面 动态 何动态 | 更新日期: 2023-09-27 18:27:00

我有这个类:

[NotifyPropertyChangedAspect] // my own aspect implementation...
class Foo {
    [OnSetAspect("OnSetExamplaryProperty")] // my own aspect implementation as well...
    public int ExamplaryProperty { get; set; }
    void OnSetExamplaryProperty() { /* do stuff... */ }
    public bool Condition { get; set; }
    [DependsOnAspect("Condition")]
    public bool Dependent { get; set; }
}

每当Condition发生变化时,我也想用PropertyName == "Dependent"激发PropertyChanged。我知道我可以反之亦然(在Condition上应用方面及其相关属性,或者只在构造函数中添加一个PropertyChanged处理程序),但我希望它是这样的:-)

以下是我能想到的可能的解决方案:

  1. 以某种方式在编译过程中注入我自己的OnSetAspect(使用Emit覆盖CompileTimeInitialize?)
  2. 不知何故,在运行时注入了我自己的OnSetAspect(再说一遍,如何?)
  3. 使用IAspectProvider应用我自己的OnSetAspect(我猜这里……不太确定可行性和/或实现的简单性)

那么,我该如何填充我的DependsOnAspect类主体来实现我的目标呢?

[Serializable]
public class DependsOnAspect : LocationInterceptionAspect {
    /* what goes here? */
}

最简单的解决方案是什么?

如何动态应用方面

在我看来,您应该在此处拦截set_Condition并激发PropertyChanged事件。因此,DependsOnAspect实际上不需要是一个方面(您不需要转换Dependent,因为它具有it属性上的属性),而只是一个常规属性。

大纲是:NotifyPropertyChangedAspect将向所有属性设置器提供OnMethodBoundaryAspect(它将实现IAspectProvider),并分析[DependsOn]属性的所有属性(在构建时)。在运行时,每个属性setter方面将为具有指向特定属性的[DependsOn]属性的所有属性激发PropertyChangedEvent

public class DependsOnAttribute : Attribute { ... }
[PSerializable]
[IntroduceInterface(typeof(INotifyPropertyChanged))]
public class NotifyPropertyChangedAspect : InstanceLevelAspect, IAspectProvider, INotifyPropertyChanged
{
    IEnumerable<AspectInstance> IAspectProvider.ProvideAspects(object targetElement)
    {
        // targetElement is Type, go through it's properties and provide SetterInterceptionAspect to them
    }
    public override void CompileTimeInitialize( Type type, AspectInfo aspectInfo )
    {
        // scan for [DependsOn] here
    }
    [PSerializable]
    public class SetterInterceptionAspect : OnMethodBoundaryAspect
    {
        // ...
        public override void OnExit(MethodExecutionArgs args)
        {
            // fire PropertyChanged event here
        }
        // ...
    }
    // ...
}

你可能需要对它进行一点修改,但我希望这将作为一个大纲使用。