2016-01-07 62 views
1

我正在嘗試爲IQueryable<T>創建通用擴展方法。 T是摘要Player,IQueryable可以包含具體類型GoalkeeperStriker關於收集各種派生類型的通用LINQ to SQL擴展方法

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的情況下,我想繼續使用鏈式擴展方法並保持良好的性能?

回答

0

您可以創建另一個擴展方法,並把有一個邏輯:

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>());