【问题标题】:Making a method generic使方法泛型
【发布时间】:2022-01-03 17:17:33
【问题描述】:

我有以下对象:

public class Store : BaseEntity
{
  public virtual List<ConsumerClubDto>? RelatedConsumerClubs { get; set; }
  public virtual List<GiftDto>? RelatedGifts { get; set; }
}

这两个列表从同一个接口实现。

我在每个列表上运行以下扩展方法。 此时我已经复制了这个方法——一个在 ConsumerClubDto 上运行,另一个是 GiftDto。

public static async Task UpdateList(this List<ConsumerClubDto>? clubsDto, Store storeFromRepo, AppDbContext dbContext)
  {
    if (clubsDto?.Count > 0)
    {
      foreach (ConsumerClubDto clubDto in clubsDto)
      {
        if ((storeFromRepo.RelatedConsumerClubs?.FindIndex(x => x.Id == clubDto.Id) == -1))
        {
          ConsumerClub t = await dbContext.ConsumerClubs.FindAsync(clubDto.Id);
          storeFromRepo.RelatedConsumerClubs.Add(t);
        }
      }
      List<ConsumerClub> clubsToRemove = new List<ConsumerClub>();
      foreach (ConsumerClub club in storeFromRepo.RelatedConsumerClubs)
      {
        if (clubsDto.FindIndex(x => x.Id == club.Id) == -1)
          clubsToRemove.Add(club);
      }
      if (clubsToRemove.Count > 0)
      {
        foreach (ConsumerClub club in clubsToRemove)
          storeFromRepo.RelatedConsumerClubs.Remove(club);
      }
    }
}

我确信我可以编写一个通用方法并避免重复代码。我不确定如何。

欢迎指点。

【问题讨论】:

  • public static async Task UpdateList(this List&lt;ICommonInterfaceName&gt;? clubsDto, Store storeFromRepo, AppDbContext dbContext) 有效吗? (将ICommonInterfaceName替换为你提到的通用接口名称)

标签: c# asp.net .net .net-core


【解决方案1】:

根据您的类层次结构、基类和实现的接口,可能会有更好的解决方案。但是为了简单地避免一遍又一遍地重复代码并且不更改现有类或没有通用基类和接口,这可能是一个好的开始。

在第一次运行中,我们需要将方法与StoreAppDbContext 解耦。这可以通过使用函数式编程范式来实现:

public static async Task UpdateList(this List<ConsumerClubDto>? clubsDto, List<ConsumerClubDto>? listInStoreFromRepo, Func<ConsumerClubDto, Task<ConsumerClub>> lookupAsync, Func<ConsumerClubDto, ConsumerClubDto, bool> match)
{
    if (clubsDto?.Count > 0)
    {
        foreach (ConsumerClubDto clubDto in clubsDto)
        {
            if ((listInStoreFromRepo?.FindIndex(x => match(x, clubDto)) == -1))
            {
                ConsumerClub t = await lookupAsync(clubDto);
                listInStoreFromRepo.Add(t);
            }
        }
        List<ConsumerClub> clubsToRemove = new List<ConsumerClub>();
        foreach (ConsumerClub club in listInStoreFromRepo)
        {
            if (clubsDto.FindIndex(x => match(x, club)) == -1)
                clubsToRemove.Add(club);
        }
        if (clubsToRemove.Count > 0)
        {
            foreach (ConsumerClub club in clubsToRemove)
                listInStoreFromRepo.Remove(club);
        }
    }
}

在第二次运行中,我们可以引入泛型类型参数来替换ConsumerClubDtoConsumerClubConsumerClub 似乎继承自 ConsumerClubDto。基于此,我们可以将代码重构为如下形式:

public static async Task UpdateList<TDto, T>(this List<TDto>? dtoList, List<TDto>? listInStoreFromRepo, Func<TDto, Task<T>> lookupAsync, Func<TDto, TDto, bool> match) where T : TDto
{
    if (dtoList?.Count > 0)
    {
        foreach (TDto dto in dtoList)
        {
            if ((listInStoreFromRepo?.FindIndex(x => match(x, dto)) == -1))
            {
                T t = await lookupAsync(dto);
                listInStoreFromRepo.Add(t);
            }
        }
        List<T> clubsToRemove = new List<T>();
        foreach (T o in listInStoreFromRepo)
        {
            if (dtoList.FindIndex(x => match(x, o)) == -1)
                clubsToRemove.Add(o);
        }
        if (clubsToRemove.Count > 0)
        {
            foreach (T club in clubsToRemove)
                listInStoreFromRepo.Remove(club);
        }
    }
}

最后你可以改变你现有的代码直接调用这个泛型方法,或者你可以改变你现有的方法来使用泛型方法来避免重复代码。

public static async Task UpdateList(this List<ConsumerClubDto>? clubsDto, Store storeFromRepo, AppDbContext dbContext)
{
    await clubsDto.UpdateList(
        storeFromRepo.RelatedConsumerClubs,
        dto => dbContext.ConsumerClubs.FindAsync(dto.Id),
        (x, y) => x.Id == y.Id);
}

【讨论】:

  • 谢谢!它给了我我需要的方向。最终,我没有将它设置为扩展方法,而是简单的实用通用方法。谢谢!
猜你喜欢
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
相关资源
最近更新 更多