Reputation: 199
I am trying to get my head around Generics and am refactoring an existing class. I would appreciate feedback on whether it could be done better.
I have a number of ViewModels which implement similar behaviour and could be derived from a common class. An example would be:
public class SelectSupplierViewModel : SelectViewModel<SupplierAModel>
SupplierAModel is an ISelectModel.
The following class enables a view which displays a menu of items to work with multiple types of data
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 is hooked up to a handler in a separate class. It is executed on the earlier '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?
}
It was not possible to have a method accepting a SelectSupplierViewModel as the SelectViewModel class is expecting SelectViewModel.
Thankyou!
Upvotes: 1
Views: 122
Reputation: 8452
You could add the deriving type to the type parameters of SelectViewModel<>
like so:
public class SelectViewModel<TModel, TViewModel> : ViewModelBase
where TModel : ISelectModel, TViewModel: SelectViewModel<TModel, TViewModel>
{
Note that you have to add a generic type constraint for TViewModel
so you can cast this
to TViewModel
when invoking the event handler.
Use TViewModel
for your event declaration:
public Action<TViewModel> OnItemSelected;
...and for its invocation:
OnItemSelected?.Invoke((TViewModel)this);
Deriving from the new base class is similar -- just add the type you are about to declare to the type parameter list:
public class SelectSupplierViewModel
: SelectViewModel<SupplierAModel, SelectSupplierViewModel>
{
Here is a working example: https://dotnetfiddle.net/8gHBwj
Upvotes: 2