Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Func<> and generics

Tags:

c#

generics

So, I'm a bit out of my comfort zone when dealing with Func<>, Generics and lambda expressions but I think I get the general idea (sort of) but still a bit confused.

I've implemented the SortableObservableCollection class (taken from online somewhere - thanks to whoever it was I got it from!) and it is used like this:

_lookuplistViewModel.Sort(x => x.BrandName, ListSortDirection.Ascending);

where x is the object type implemented by the sortable collection. In this instance, BrandName is a property of the type of object implemented, but I want to use the above code in a generic class and pass in the property on which to sort. The Sort method looks like this:

public void Sort<TKey>(Func<T, TKey> keySelector, ListSortDirection direction)
{
  switch (direction)
  {
    case ListSortDirection.Ascending:
      {
        ApplySort(Items.OrderBy(keySelector));
        break;
      }
    case System.ComponentModel.ListSortDirection.Descending:
      {
        ApplySort(Items.OrderByDescending(keySelector));
        break;
      }
  }
}

The generic class on which the Sort method is called is defined like this:

public class ExtendedLookupManagerViewModel<VMod, Mod> : LookupManagerViewModel
where VMod : ExtendedLookupViewModel
where Mod : ExtendedLookupModelBase

and I'd like to create an instance of it like this:

_medProd = new ExtendedLookupManagerViewModel<MedicinalProductViewModel, MedicinalProduct>(string property);

where property is the property on which to sort. Ideally this should be type safe, but a string will suffice.

Can anyone help steer me in the right direction please?

like image 959
pilsdumps Avatar asked Jul 27 '10 12:07

pilsdumps


3 Answers

Just make your constructor sig match the sig for the sort method, and cache the params for using in the collection when Sort() is called. So not "string property" but rather whatever the sig is for the sort method.

The passed parameter then would be a func that could be type specific and directing you to the element, the instantiation would be

_medProd = new ExtendedLookupManagerViewModel<MedicinalProductViewModel, MedicinalProduct>(x => x.BrandName, ListSortDirection.Ascending);
like image 93
Jimmy Hoffa Avatar answered Oct 01 '22 23:10

Jimmy Hoffa


You should not be accepting a string property argument, but rather a Func<T, IComparable> where T is probably either VMod or Mod, depending what you are trying to sort.

like image 33
recursive Avatar answered Oct 01 '22 23:10

recursive


Well, your Sort method is only generic in TKey - where does T come from? I suspect it should either be Func<VMod, TKey> or Func<Mod, TKey> but I'm unsure which from what you've shown.

What would BrandName be a property of - MedicinalProductViewModel or MedicinalProduct? Assuming it's MedicinalProduct, your method should be declared as:

public void Sort<TKey>(Func<Mod, TKey> keySelector, ListSortDirection direction)

At that point I suspect it will work...

like image 30
Jon Skeet Avatar answered Oct 01 '22 22:10

Jon Skeet