0

I have an object Song that i like to sort based on a parameter given to me from the frontend.

 public class Song
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Year { get; set; }
    public string Artist { get; set; }
    public int? Bpm { get; set; }
    public int Duration { get; set; }
    public string Genre { get; set; }
    public string Album { get; set; }
}

Is it possible to sort the SongList based on the sort parameter? The parameter can be for example Album, title or artist but basically it could be any of the properties in the Song object.

 private List<Song> FilterSongs (List<Song> songs, string genre, string sortBy)
    {
        List<Song> filteredList = songs.Where(song => song.Genre.Contains(genre)).OrderBy(song => song.sortBy).ToList();
        return filteredList;
    }

I could just make a case switch with multiple filter options but I was hoping someone would know a nice and clean query.

Proliges
  • 369
  • 3
  • 23
  • Does this answer your question? [C# - code to order by a property using the property name as a string](https://stackoverflow.com/questions/1689199/c-sharp-code-to-order-by-a-property-using-the-property-name-as-a-string) – apocalypse Jul 04 '20 at 12:25

3 Answers3

1

If you don't want to change method signature, you could use Reflection, like the following code :

1 - Filter method

private List<Song> FilterSongs(List<Song> songs, string genre, string sortBy)
{
    PropertyInfo property = typeof(Song).GetProperty(sortBy);

    return songs
        .Where(song => song.Genre.Contains(genre))
        .OrderBy(song => property.GetValue(song))
        .ToList();
}

2 - Call the method like :

List<Song> filtredSongs = FilterSongs(songs, "bob", "Album");

I hope you find this helpful.

Mohammed Sajid
  • 4,572
  • 2
  • 12
  • 16
0

You can make FilterSongs generic and change your method signature to accept selector function for order:

private List<Song> FilterSongs<TOrder>(List<Song> songs, string genre, Func<Song, TOrder> sortBy)
{
    List<Song> filteredList = songs.Where(song => song.Genre.Contains(genre)).OrderBy(sortBy).ToList();
    return filteredList;
}

And possible use :

FilterSongs(..., ..., s => s.Album);
Guru Stron
  • 21,224
  • 3
  • 19
  • 37
0

Here's another solution

public static List<Song> FilterSongs<TOrder>(this List<Song> songs, string genre, Expression<Func<Song, TOrder>> sortBy)
{
    List<Song> filteredList = songs
        .Where(song => song.Genre.Contains(genre))
        .OrderBy(song=> sortBy.Compile()(song))
        .ToList();

    return filteredList;
}

and it's usage

var result = songs.FilterSongs("someGenre", s => s.Artist);
Manuel
  • 31
  • 4