C# 仅当基方法完成时调用派生方法
我觉得这是一种常见的情况,我很好奇是否有最佳实践解决方案 与所有WPF一样,我在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
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); });
}