c# - Generic LINQ to SQL Extension Methods on collection of various derived types -
i'm trying create generic extension method iqueryable<t>
. t abstract player
, iqueryable can contain concrete types goalkeeper
, striker
.
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; } }
the extension methods working (the simple ones) this:
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)); }
which can use this:
var badgoalies = players.oftype<goalkeeper>().notperforming(); var badstrikers = players.oftype<striker>().notperforming();
so want query for players not performing well.
var badplayers = players.notperforming();
which can't seem work properly.
public static iqueryable<t> notperforming<t>(this iqueryable<t> players) t : player { // here? }
i tried things like...
return players.oftype<striker>().notperforming() .union( players.oftype<goalkeeper>().notperforming() );
which doesn't work.
what best practice way of doing -- , without leaving linq-to-sql because i'd keep chaining extension methods -- , keeping performance in mind?
you can create extension method , put there logic:
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)); }
and use:
var badplayers = players.notperforming();
or approach:
public static iqueryable<player> notperforming<t>(this iqueryable<player> players) 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)); }
and use:
var badstrikers = players.notperforming<striker>(); var badgoalkeepers = players.notperforming<goalkeeper>(); var badplayers = players.notperforming<striker>() .concat(players.notperforming<goalkeeper>());
Comments
Post a Comment