使用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
{
}
这对我来说就像一个酸痛的拇指!考虑到使用空接口用于泛型约束,我认为实现并不优雅。
我应该如何解决这个问题?
答案 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
事件。
如果没有任何其他信息,我会说这里最好的方法是有两种不同的视图模型类型。即类似于您提议的解决方法,除了您摆脱IModel
和ViewModel<T>
,并且只有PropertyModel<T>
和CollectionModel<T>
。毕竟,无论如何,两者都不可能以任何有意义的方式重叠。