我试图了解Generics并重构现有的课程。我希望得到关于是否可以做得更好的反馈。
我有许多ViewModel实现类似的行为,可以从一个公共类派生。一个例子是:
public class SelectSupplierViewModel : SelectViewModel<SupplierAModel>
SupplierAModel是一个ISelectModel。
以下类启用一个视图,该视图显示项目菜单以使用多种类型的数据
public class SelectViewModel<T> : ViewModelBase where T : ISelectModel
{
public Action<SelectViewModel<T>> OnItemSelected;
public IEnumerable<T> Selections { get; set; }
public T SelectedItem
{
get { return null; }
set {
RaisePropertyChanged();
OnItemSelected?.Invoke(this);
}
}
.
.
.
OnItemSelected连接到单独的类中的处理程序。它在之前的'Invoke'上执行:
private void OnSupplierSelected(SelectViewModel<SelectAModel> viewModel)
{
// When I inspect viewModel I can see that viewModel is a
// SelectSupplierViewModel, and I need to access properties on
// this.
// Is it possible to do so without casting viewModel to
// SelectSupplierViewModel?
}
由于SelectViewModel类需要SelectViewModel,因此不可能有一个接受SelectSupplierViewModel的方法。
三江源!
答案 0 :(得分:2)
您可以将派生类型添加到SelectViewModel<>
的类型参数中,如下所示:
public class SelectViewModel<TModel, TViewModel> : ViewModelBase
where TModel : ISelectModel, TViewModel: SelectViewModel<TModel, TViewModel>
{
请注意,您必须为TViewModel
添加泛型类型约束,以便在调用事件处理程序时将this
强制转换为TViewModel
。
使用TViewModel
进行活动声明:
public Action<TViewModel> OnItemSelected;
......以及它的调用:
OnItemSelected?.Invoke((TViewModel)this);
从新基类派生类似 - 只需将要声明的类型添加到类型参数列表中:
public class SelectSupplierViewModel
: SelectViewModel<SupplierAModel, SelectSupplierViewModel>
{
以下是一个工作示例:https://dotnetfiddle.net/8gHBwj