我可以在单个泛型类型上指定多个约束吗?

时间:2015-02-19 11:42:04

标签: c# .net generics mvvm

使用MVVM设计模式示例;说我有一个Model和一个ViewModel:

public class UserAccountModel
{
}

public class ViewModel<TModel>
{
    public TModel Model { get; private set; }

    public ViewModel(TModel model)
    {
        this.Model = model;
    }
}

ViewModel<UserAccountModel> = new ViewModel(new UserAccountModel());

但是现在我需要添加一些功能来监听模型,这样当它们发生变化时,我可以相应地更新视图:

public class UserAccountModel : INotifyPropertyChanged
{
    //Implementation for INotifyPropertyChanged
}

public class ViewModel<TModel> where TModel : INotifyPropertyChanged
{
    public TModel Model { get; private set; }

    public ViewModel(TModel model)
    {
        this.Model = model;
    }
}

ViewModel<UserAccountModel> = new ViewModel(new UserAccountModel());

这适用于您想要确定属性已更改的模型,但现在我还要创建实现不同界面的集合模型:

public class UserAccountCollectionModel : ObservableCollection<UserAccount>
{
}

public ViewModel<UserAccountCollectionModel> vm = new ViewModel<UserAccountCollectionModel>(new UserAccountCollectionModel());

此错误导致UserAccountCollectionModel未实施INotifyPropertyChanged - 而是实施INotifyCollectionChanged

所以我想要的是:

public class ViewModel<TModel> where TModel : INotifyPropertyChanged (or) INotifyCollectionChanged
{
}

AFAIK在C#中无法做到这一点,所以我的解决方法是:

public interface IModel
{
}

public class PropertyModel : INotifyPropertyChanged, IModel
{
}

public class CollectionModel : ObservableCollection<PropertyModel>, IModel
{
}

public class ViewModel<TModel> where TModel : IModel
{
}

这对我来说就像一个酸痛的拇指!考虑到使用空接口用于泛型约束,我认为实现并不优雅。

我应该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

你有一个选择是放宽ViewModel<TModel>类的约束,但是让构造函数变为私有,然后创建两个强类型的静态工厂方法,为你执行约束。

像这样:

public class ViewModel<TModel>
{
    public TModel Model { get; private set; }

    public static ViewModel<T> CreateFromObject<T>(T model)
        where T : INotifyPropertyChanged
    {
        return new ViewModel<T>(model);
    }

    public static ViewModel<T> CreateFromCollection<T>(T model)
        where T : INotifyCollectionChanged
    {
        return new ViewModel<T>(model);
    }

    private ViewModel(TModel model)
    {
        this.Model = model;
    }
}

答案 1 :(得分:0)

如果不了解您打算如何使用ViewModel<T>课程,就无法提供正确实施方法的建议。但至少可以评论C#方面...

就约束条件而言,允许多个可选的约束(即类可以实现其中任何一个),根本不会有任何意义。泛型类型中约束的唯一目的是对类型提供编译时限制,该类型允许泛型类型的代码使用该类型执行操作。

E.g。如果您需要INotifyPropertyChanged,那么在您的泛型类型中,您可以订阅受限制的对象上的PropertyChanged事件(即类型参数类型的任何实例)。

但是如果允许泛型类型参数简单地实现接口某些其他接口,那么你可以在泛型类型中用它做什么?什么都没有,除了你能用它做什么,它完全不受约束。毕竟,“或”约束基本上表示可以省略任一约束,如果是这种情况,那么就不能保证例如将出现PropertyChanged事件。


如果没有任何其他信息,我会说这里最好的方法是有两种不同的视图模型类型。即类似于您提议的解决方法,除了您摆脱IModelViewModel<T>,并且只有PropertyModel<T>CollectionModel<T>。毕竟,无论如何,两者都不可能以任何有意义的方式重叠。