如何在不重复代码的情况下将相同的功能添加到不同的基类?

时间:2017-11-23 20:59:11

标签: c# generics inheritance

我目前有两个项目正在进行中。一个是WPF项目,并使用MvvmLight框架。另一个是使用FreshMVVM的Xamarin.Forms项目。这两个框架都有自己的INotifyPropertyChanged实现,用作相应项目中所有ViewModel的基类。

在WPF项目中,我添加了一个实现INotifyDataErrorInfo的ValidatedViewModel,以便我可以轻松地对用户输入进行验证:

public abstract class ValidatedViewModel : ViewModelBase, INotifyDataErrorInfo
{
    protected ValidatedViewModel() : base()
    {
        PropertyChanged += (sender, args) => ValidateProperty(args.PropertyName);
    }

    private readonly Dictionary<string, IEnumerable<string>> _validationErrors = new Dictionary<string, IEnumerable<string>>();
    public IEnumerable GetErrors(string propertyName)
    {
        return _validationErrors.ContainsKey(propertyName) ? _validationErrors[propertyName] : null;
    }

    public bool HasErrors => _validationErrors.Any();
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    private void ValidateProperty(string propertyName)
    {
        var value = GetValue(propertyName);
        var results = new List<ValidationResult>();
        bool valid = Validator.TryValidateProperty(value,
            new ValidationContext(this, null, null) {MemberName = propertyName}, results);

        if (valid)
        {
            _validationErrors.Remove(propertyName);
        }
        else
        {
            _validationErrors[propertyName] = results.Select(r => r.ErrorMessage);
        }

        RaiseErrorsChanged(propertyName);
    }

    protected void RaiseErrorsChanged(string propertyName)
    {
        ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
    }

    private object GetValue(string propertyName)
    {
        PropertyInfo propInfo = GetType().GetProperty(propertyName);
        return propInfo.GetValue(this);
    }
}

由于我也需要在我的Xamarin.Forms应用程序中进行验证,因此我必须复制并粘贴此类,仅更改基类。作为程序员,我讨厌不得不像这样重复代码块,所以我想将这个(以及一些其他常见功能,如http客户端包装器)放入一个可供两个项目使用的通用程序集中。不幸的是,我还没有找到实际共享ViewModelBase类的方法,因为尽管两个版本在其他方面完全相同,但它们都扩展了不同的基类。

如果我能做到这一点:

public abstract class ValidatedViewModel<BaseViewModel> : BaseViewModel, INotifyDataErrorInfo where BaseViewModel : INotifyPropertyChanged

或者这个:

public class WPFViewModelBase : ViewModelBase, ValidatedeViewModel
public class XFViewModelBase : FreshBasePageModel, ValidatedViewModel
那么这不会成为问题。不幸的是,据我所知,这两件事都是不可能的。

跳出来的唯一解决方案是拥有一个ViewModelValidatorWPFViewModelBaseXFViewModelBase每个实例化构建,并转发INofityDataErrorInfo调用,但这看起来很笨重,并没有完全消除代码重复,因为我仍然会在两个不同的地方拥有所有相同的转发代码。

有什么方法可以消除所有代码重复吗?

0 个答案:

没有答案