Шаблон проектирования в C#, чтобы уменьшить количество циклов дублирования кода в списках классов - PullRequest
0 голосов
/ 05 мая 2020

У меня есть представитель с элементами мультимедиа Каждый элемент может иметь несколько закладок и комментариев от разных пользователей.

Когда я прихожу для обновления репозитория, мне нужно получить все существующие комментарии и закладки и добавить новые комментарии и закладки, код работает, но я не могу придумать чистый способ сделать это в целом, который уменьшит дублирование, поскольку планируется больше таких полей

  public class MapValues
    {
        private readonly string _userName;
        private readonly Media _media;
        private readonly IMediaRepository _mediaRepo;

        public MapValues(string userName, Media media, IMediaRepository mediaRepo)
        {
            _userName = userName;
            _media = media;
            IMediaRepository = mediaRepo;
        }

        public async Task<Media> AppendExistingUserValues(Media updatedMedia, string userName)
        {
            var existingMedia = await _mediaRepo.GetByIdAsync(updatedMedia.Id);
            var existingBookmarks = GetBookmarksExcludingUser(userName, existingMedia);
            var existingComments = GetCommentsExcludingUser(userName, existingMedia);

            if (updatedMedia.Bookmarks.Any())
            {
                existingBookmarks.AddRange(updatedMedia.Bookmarks);
            }

            if (updatedMedia.Comments.Any())
            {
                existingComments.AddRange(updatedMedia.Comments);
            }

            updatedMedia.Bookmarks = existingBookmarks;
            updatedMedia.Comments = existingComments;
            return updatedMedia;
        }


        private List<MediaBookmarks> GetBookmarksExcludingUser(string userName, Media media)
        {
            var exisitingBookmarks = new List<MediaBookmarks>();
            if (media?.Bookmarks != null)
            {
                exisitingBookmarks.AddRange(media.Bookmarks
                    .Where(x => !string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase)).ToList());
            }

            return exisitingBookmarks;
        }

        private List<MediaComments> GetCommentsExcludingUser(string userName, Media media)
        {
            var exisitingComments = new List<MediaComments>();
            if (media?.Bookmarks != null)
            {
                exisitingComments.AddRange(media.Comments
                    .Where(x => !string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase)).ToList());
            }

            return exisitingComments;
        }
    }

    public class Media
    {
        public IEnumerable<MediaBookmarks> Bookmarks { get; set; }

        public IEnumerable<MediaComments> Comments { get; set; }
        public string Id { get; set; }
    }

    public class MediaBookmarks
    {
        public string Name { get; set; }
    }

    public class MediaComments
    {
        public string Name { get; set; }
    }

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Если вы создаете интерфейс (IMediaItem), вы можете реализовать его для каждого из ваших c классов (закладки и комментарии).

public interface IMediaItem //This could even be a class if required
{
    public string Name { get; set; }
}

 public class MediaBookmarks : IMediaItem 
{
  public string Name { get; set; }
}

public class MediaComments : IMediaItem 
{
  public string Name { get; set; }
}

Затем в ваших GetBookmarksExcludingUser и GetCommentsExcludingUser можно объединить в это:

private List<IMediaItem> GetMediaItemExcludingUser(string userName, IEnumerable<IMediaItem> sourceList)
    {
        var existingItems = new List<IMediaItem>();
        if (sourceList != null)
        {
            existingItems.AddRange(sourceList
                .Where(x => !string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase)).ToList());
        }

        return existingItems;
    }

Вызовите этот метод следующим образом:

var existingBookmarks = GetMediaItemExcludingUser(userName, existingMedia?.Bookmarks).Cast<MediaBookmarks>();
0 голосов
/ 05 мая 2020

Насколько я могу судить, все это можно переписать на

 public async Task<Media> AppendExistingUserValues2(Media updatedMedia, string userName)
    {
        var existingMedia = await _mediaRepo.GetByIdAsync(updatedMedia.Id);


        updatedMedia.Bookmarks = updatedMedia.Bookmarks
            .Union(existingMedia.Bookmarks.Where(x => !string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase))).ToList();

        updatedMedia.Comments = updatedMedia.Comments
            .Union(existingMedia.Comments.Where(x => !string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase))).ToList();

        return updatedMedia;
    }

Мне также нравится использовать методы расширения, чтобы сделать строку более читаемой, поэтому с помощью помощника. *

можно просто написать.

public async Task<Media> AppendExistingUserValues2(Media updatedMedia, string userName)
        {
            var existingMedia = await _mediaRepo.GetByIdAsync(updatedMedia.Id);


            updatedMedia.Bookmarks = updatedMedia.Bookmarks
                .Union(existingMedia.Bookmarks.Where(x => x.Name.IsSame(userName))).ToList();

            updatedMedia.Comments = updatedMedia.Comments
                .Union(existingMedia.Comments.Where(x => x.Name.IsSame(userName))).ToList();

            return updatedMedia;
        }
...