【问题标题】:Generic LINQ to SQL Extension Methods on collection of various derived types各种派生类型集合的通用 LINQ to SQL 扩展方法
【发布时间】:2016-04-11 23:27:45
【问题描述】:

我正在尝试为IQueryable<T> 创建一个通用扩展方法。 T 是一个抽象 Player,而 IQueryable 可以包含具体类型 GoalkeeperStriker

public abstract class Player
{
    public string Name { get; set; }
    public string Fouls { get; set; }
}

public class Goalkeeper : Player
{
    public int Saves { get; set; }

}

public class Striker : Player
{
    public int Goals { get; set; }
}

有效的扩展方法(简单的)如下所示:

public static IQueryable<Goalkeeper> NotPerforming(this IQueryable<Goalkeeper> goalkeepers)
{
    return goalkeepers.Where(g => g.Saves < goalkeepers.Average(x => x.Saves));
}

public static IQueryable<Striker> NotPerforming(this IQueryable<Striker> strikers)
{
    return strikers.Where(g => g.Goals < strikers.Average(x => x.Goals));
}

我可以这样使用:

var badGoalies = players.OfType<Goalkeeper>().NotPerforming();
var badStrikers = players.OfType<Striker>().NotPerforming();

所以现在我想查询所有表现不佳的玩家

var badPlayers = players.NotPerforming();

我似乎无法正常工作。

public static IQueryable<T> NotPerforming<T>(this IQueryable<T> players)
    where T : Player
{
    // what to do here?
}

我尝试过......

return players.OfType<Striker>().NotPerforming()
          .Union(
              players.OfType<Goalkeeper>().NotPerforming()
          );

这不起作用。

这样做的最佳实践方式是什么——并且不离开 LINQ-to-SQL,因为我想继续链接扩展方法——并牢记良好的性能?

【问题讨论】:

    标签: c# linq-to-sql extension-methods


    【解决方案1】:

    您可以创建另一个扩展方法并在那里放置逻辑:

    public static IQueryable<Player> NotPerforming(this IQueryable<Player> players)
    {
        var notPerformingGoalKeepers = players.NotPerformingGoalkeepers();
        var notPerformingStrikers = players.NotPerformingStrikers();
    
        return notPerformingGoalKeepers.Cast<Player>()
            .Concat(notPerformingStrikers);
    }
    
    public static IQueryable<Goalkeeper> NotPerformingGoalkeepers(this IQueryable<Player> players)
    {
        var goalkeepers = players.OfType<Goalkeeper>();
        return goalkeepers.Where(g => g.Saves < goalkeepers.Average(x => x.Saves));
    }
    
    public static IQueryable<Striker> NotPerformingStrikers(this IQueryable<Player> players)
    {
        var strikers = players.OfType<Striker>();
        return strikers.Where(g => g.Goals < strikers.Average(x => x.Goals));
    }
    

    并使用:

    var badPlayers = players.NotPerforming();
    

    或其他方法:

    public static IQueryable<Player> NotPerforming<T>(this IQueryable<Player> players) where T : Player
    {
        if (typeof(T) == typeof(Goalkeeper))
        {
            return players.OfType<Goalkeeper>().NotPerforming();
        }
    
        if (typeof(T) == typeof(Striker))
        {
            return players.OfType<Striker>().NotPerforming();
        }
    
        return null;
    }
    
    private static IQueryable<Goalkeeper> NotPerforming(this IQueryable<Goalkeeper> goalkeepers)
    {
        return goalkeepers.Where(g => g.Saves < goalkeepers.Average(x => x.Saves));
    }
    
    private static IQueryable<Striker> NotPerforming(this IQueryable<Striker> strikers)
    {
        return strikers.Where(g => g.Goals < strikers.Average(x => x.Goals));
    }
    

    并使用:

    var badStrikers = players.NotPerforming<Striker>();
    var badGoalkeepers = players.NotPerforming<Goalkeeper>();
    
    var badPlayers = players.NotPerforming<Striker>()
        .Concat(players.NotPerforming<Goalkeeper>());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多