这是我认为您要求的解决方案。
首先,基础存储库。我创建了一个基础存储库,因为我希望您不会将这种疯狂暴露给应用程序,而只会暴露给存储库。
abstract class BaseRepo<TEntity>
{
// If you're using Entity Framework, this method could
// be implemented here instead.
protected abstract IQueryable<TEntity> Entities { get; }
protected IList<TReturn> GetAllPaged<TResult, TKey, TGroup, TReturn>(
List<Expression<Func<TEntity, bool>>> predicates,
Expression<Func<TEntity, TResult>> firstSelector,
Expression<Func<TResult, TKey>> orderSelector,
Func<TResult, TGroup> groupSelector,
Func<IGrouping<TGroup, TResult>, TReturn> selector)
{
return predicates
.Aggregate(Entities, (current, predicate) => current.Where(predicate))
.Select(firstSelector)
.OrderBy(orderSelector)
.GroupBy(groupSelector)
.Select(selector)
.ToList();
}
}
然后执行。
class HorseRepo : BaseRepo<Horse>
{
// This will of course be some data source
protected override IQueryable<Horse> Entities
{
get
{
return new List<Horse> {
new Horse { Id = 1, Name = "Mr Horse", Color = "Brown" },
new Horse { Id = 2, Name = "Mrs Horse", Color = "White" },
new Horse { Id = 3, Name = "Jr Horse", Color = "White" },
new Horse { Id = 4, Name = "Sr Horse", Color = "Black" },
new Horse { Id = 5, Name = "Dr Horse", Color = "Brown" },
}.AsQueryable();
}
}
// This is what I think you should expose to the application
// This is the usage of the expression fest above.
public IEnumerable<GroupedHorses> GetGroupedByColor() {
return horseRepo.GetAllPaged(
new List<Expression<Func<Horse, bool>>> {
h => h.Name != string.Empty,
h => h.Id > 0
},
h => new HorseShape { Id = h.Id, Name = h.Name, Color = h.Color },
hs => hs.Name,
hs => hs.Color,
g => new GroupedHorses
{
Color = g.Key,
Horses = g.ToList()
}
);
}
}
需要一些类:
class GroupedHorses
{
public string Color { get; set; }
public IList<HorseShape> Horses { get; set; }
}
class HorseShape
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
// Define other methods and classes here
class Horse
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string UninterestingProperty { get; set; }
}