C# 仅当基方法完成时调用派生方法

C# 仅当基方法完成时调用派生方法,c#,wpf,inheritance,overriding,dry,C#,Wpf,Inheritance,Overriding,Dry,我觉得这是一种常见的情况,我很好奇是否有最佳实践解决方案 与所有WPF一样,我在ViewModelBase上有一个方法,用于设置属性值并调用OnPropertyChanged: protected virtual void SetProperty<T>(string propertyName, ref T oldValue, T newValue) { if (Equals(oldValue, newValue)) return; oldValue = newVal

我觉得这是一种常见的情况,我很好奇是否有最佳实践解决方案

与所有WPF一样,我在
ViewModelBase
上有一个方法,用于设置属性值并调用
OnPropertyChanged

protected virtual void SetProperty<T>(string propertyName, ref T oldValue, T newValue)
{
    if (Equals(oldValue, newValue)) return;

    oldValue = newValue;
    OnPropertyChanged(propertyName);
}
我的问题是,如果
Base
由于项目相等而过早返回,我不想调用我的
派生的
代码。当然,我知道有几种方法可以做到这一点:

  • SetProperty
    可以返回
    派生的
    检查的bool(由于此方法的其他1000个用户不关心返回值,因此看起来很难看)
  • 重新检查这两个属性在
    派生中是否相等(简单,但不干燥)

  • 我总是喜欢保持干燥,我只是好奇是否有一个共同的解决方案,这个问题被认为是一个最佳实践?在整个框架中,这似乎是一个非常常见的场景。

    看起来像是妄想症,但如果它如此重要,那么您可能应该尝试在这种情况下不使用继承,并创建带有验证的基类(并且,可能还为两个ViewModelBase创建抽象超类)

    您可以在新的派生类中将委托方法添加到onpropertychange中,当触发onpropertychange时,它将在调用到事件的新方法中运行ValidateProperty方法。因此,您可以删除派生方法中的Validateproperty方法,并且不需要新的重写方法,因为您可以在属性更改时触发Validateproperty。

    一个选项是使用第二个函数指定更改属性时需要执行的操作。在基类中定义一个不做任何事情的虚方法,在
    SetProperty
    中调用该方法,然后重写子类中的虚方法

    在基类中,您可以执行以下操作:

    protected virtual void SetProperty<T>(string propertyName, ref T oldValue, T newValue)
    {
        if (Equals(oldValue, newValue)) return;
    
        oldValue = newValue;
        // Validate the property that was just changed.
        PropertyValidate(propertyName, ref oldValue, newValue);
        OnPropertyChanged(propertyName);
    }
    
    protected virtual void PropertyValidate<T>(string propertyName, ref T oldValue, T newValue)
    {}
    

    如果验证失败,是否希望base.SetProperty运行?似乎您的ValidateProperty应该首先运行,并且只有在值有效时才设置base属性。ValidateProperty将在失败时返回bool或引发异常。base.SetProperty不关心验证
    ValidateProperty
    可以添加到
    Errors
    集合并禁用save按钮。只需从SetProperty返回bool即可。如果其他人不想使用它,他们不必使用。这绝对是偏执狂
    protected virtual void SetProperty<T>(string propertyName, ref T oldValue, T newValue)
    {
        if (Equals(oldValue, newValue)) return;
    
        oldValue = newValue;
        // Validate the property that was just changed.
        PropertyValidate(propertyName, ref oldValue, newValue);
        OnPropertyChanged(propertyName);
    }
    
    protected virtual void PropertyValidate<T>(string propertyName, ref T oldValue, T newValue)
    {}
    
    protected override void PropertyValidate<T>(string propertyName, ref T oldValue, T newValue)
    {
        // Do some validation, adding some red marks to bad things.
    }
    
    protected virtual void SetProperty<T>(
        string propertyName,
        ref T oldValue,
        T newValue,
        Action onChanged = null)
    {
        if (Equals(oldValue, newValue)) return;
    
        oldValue = newValue;
        onChanged?.Invoke(); // Invoke the onChanged action (if not null).
        OnPropertyChanged(propertyName);
    }
    
    protected override void SetProperty<T>(
        string propertyName,
        ref T oldValue,
        T newValue,
        Action onChanged = null)
    {
        // Wrap the given onChanged callback with a new one that also validates the property.
        base.SetProperty(propertyName, ref oldValue, newValue,
            () => { onChanged?.Invoke(); ValidateProperty(propertyName, newValue); });
    }