向派生类添加方面

时间:2015-12-10 20:42:46

标签: postsharp

我编写了一个工作正常的方面,但只在基类上,派生类什么都不做。

拜托,我缺少什么?

代码如下

public interface INotifyOnChange : INotifyPropertyChanged
{
    void OnPropertyChanged(string propertyName);
}

[Serializable]
[AspectConfiguration(AspectPriority = 10)]
[IntroduceInterface(typeof(INotifyOnChange), OverrideAction = InterfaceOverrideAction.Ignore, AncestorOverrideAction = InterfaceOverrideAction.Ignore)]
[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict, AllowMultiple = false)]
public sealed class NotifyPropertiesOnChange : InstanceLevelAspect, INotifyOnChange
{
    [IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
    public void OnPropertyChanged(string propertyName)
        => PropertyChanged?.Invoke(Instance, new PropertyChangedEventArgs(propertyName));

    [IntroduceMember(OverrideAction = MemberOverrideAction.Ignore)]
    public event PropertyChangedEventHandler PropertyChanged;

    [OnLocationSetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Property, Attributes = MulticastAttributes.Public | MulticastAttributes.Instance)]
    public void OnSetValue(LocationInterceptionArgs args)
    {
        if (args.Value == args.GetCurrentValue())
            return;

        args.ProceedSetValue();

        var notifyOnChange = args.Instance as INotifyOnChange;

        notifyOnChange?.OnPropertyChanged(args.Location.PropertyInfo.Name);
    }
}

我还使用 Inheritance = MulticastInheritance.Multicast 进行了测试但没有成功。

但是,如果我有一个像下面这样的基类,它可以工作

[NotifyOnChange]
public class EuroRate
{
    public string Currency { get; set; }
    public decimal Rate { get; set; }
    public DateTime Date { get; set; }
}

但是如果尝试派生类(当然从基类中删除方面)它不会起作用

public class EuroRate
{
    public string Currency { get; set; }
    public decimal Rate { get; set; }
    public DateTime Date { get; set; }
}

[NotifyPropertiesOnChange]
public class RateModel : EuroRate 
{
}

1 个答案:

答案 0 :(得分:1)

方面只能改变应用它的声明。对于您的方面(File k = new File(path, "Queen-BohemianRhapsody.mp3"); ContentValues values = new ContentValues(); values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath()); values.put(MediaStore.MediaColumns.TITLE, "Bohemian Rhapsody"); values.put(MediaStore.MediaColumns.SIZE, 188080); values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3"); values.put(MediaStore.Audio.Media.ARTIST, "Queen"); values.put(MediaStore.Audio.Media.DURATION, 230); values.put(MediaStore.Audio.Media.IS_RINGTONE, true); values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false); values.put(MediaStore.Audio.Media.IS_ALARM, false); values.put(MediaStore.Audio.Media.IS_MUSIC, false); Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()); Uri newUri = this.getContentResolver().insert(uri, values); RingtoneManager.setActualDefaultRingtoneUri(myActivity, RingtoneManager.TYPE_RINGTONE, newUri); ),这意味着当应用于TypeLevelAspect类时,它只能对此类直接声明的属性应用建议。基数声明的属性不会被转换(因为您需要转换基础本身)。

在这种情况下,最好的选择是依赖于组播继承本身,即在基类上应用方面。这意味着您需要处理这样一个事实,即在每个类中单独应用该方面,并开发这些方面之间的通信机制。

效果问题

您可能已经注意到,这会导致目标类的单个实例存在多个方面实例(取决于继承级别)。

您可以通过结合引入RateModel方法,事件和接口的实例级方面来优化它。这方面不会直接应用,而是通过仅仅OnPropertyChanged的主要方面通过IAspectProvider

宣传您的多播继承说明(see the documentation):

对于类型TypeLevelAspect上应用的TypeLevelAspect和[MulticastInheritance.Strict]基本相同。

原因是多播继承还考虑了多播的声明(继承多播本身);即,如果对类型应用方法级别方面,则多播继承将导致派生类继承其所有方法的方面。

另一方面,严格的继承只会导致应用的方面被继承,即只有重写方法才会有方面。