C #: сравнить разные наборы объектов с одним и тем же свойством

#c# #linq

#c# #linq

Вопрос:

У меня проблема, которую я не уверен в лучшем способе решения. И мои «решения» приводят к очень сложному коду.

Пример: в моей модели данных есть диваны и яблоки. И класс Sofa, и класс Apple имеют свойство isFavorite и дату FavoriteChange. У меня есть сервис, который я использую следующим образом:

  List<Apple> top25FavApples = _appleService.FindFavorites(25);
 List<Sofa> top25FavSofas = _sofaService.FindFavorites(25);
  

Теперь, когда у меня есть избранные яблоки и диваны, мне нужно объединить коллекции, упорядочить по FavoriteChangeDate, а затем ограничить до 25 лучших. Вот тут я и застрял.

Возможное решение: создайте промежуточный класс для хранения Apple / Sofa и FavoriteDate. Выполните выборки для коллекции промежуточных объектов, а затем запустите другой запрос, чтобы вернуть яблоки и диваны самостоятельно.

Комментарии:

1. Вы можете заставить Apple и Sofa наследовать IFavoratable интерфейс.

Ответ №1:

Лучшим решением было бы создать IFavoriteable интерфейс, который определяет FavoriteChangeDate свойство, и заставить два класса реализовать его. Затем вы можете просто выполнить приведение IFavoriteable и выполнить Linq OrderBy для него.

 class Program
{
    static void Main()
    {
        List<Apple> top25FavApples = _appleService.FindFavorites(25);
        List<Sofa> top25FavSofas = _sofaService.FindFavorites(25);

        List<IFavoriteable> top25Total = top25FavApples.Concat<IFavoriteable>(top25FavSofas)
                                                       .OrderBy(x => x.FavoriteChangeDate)
                                                       .Take(25).ToList();

    }
}

public interface IFavoriteable
{
    DateTime? FavoriteChangeDate { get; }
}

public class Apple : IFavoriteable
{
    public DateTime? FavoriteChangeDate { get; set; }
    //...
}

public class Sofa : IFavoriteable
{
    public DateTime? FavoriteChangeDate { get; set; }
    //...
}
  

Ответ №2:

Если вы не можете добавить какой-либо интерфейс или базовый класс (что было бы лучше), одним из вариантов может быть приведение к динамическому и запрос в динамическом режиме, например:

 top25FavApples.Cast<dynamic>()
    .Concat(top25Sofas.Cast<dynamic>())
    .OrderBy(x => (DateTime)x.FavoriteChangeDate).Take(25)