如何在一组通用C#类型上重用LINQ聚合查询,这些类型具有在编译时已知的通用形状或接口,而不需要使用黑魔法动态ExpressionBuilder
的东西?
例如,
// Each "reportable" class has a decimal property to sum over:
interface IReportable<T> {
Expression<T, decimal> GetSummingExpr(); // no static interface methods :(
}
public static class ReportingExtensions {
public static IQueryable<decimal> Report<T>(this IQueryable<T> qry)
{
return x => x.Sum(qry.GetSummingExpr()); // unsure if interfaces can do this
}
}
var invoices = new Invoice [] { Invoice(100.0M), ... };
var quotes = new Quote [] { Quote(50.0M), ... };
// Ideal use-cases:
var invoiceReport = invoices.AsQueryable().Report();
var quoteReport = quotes.AsQueryable().Report();
// "Reportable" class implementations:
public class Invoice : IReportable<Invoice>
{
public decimal InvoiceTotal { get; set; }
public Expression<Func<Invoice, decimal>> GetTotalExpr()
{
return x => x.InvoiceTotal;
}
}
public class Quote : IReportable<Quote>
{
public decimal QuoteTotal { get; set; }
public Expression<Func<Quote, decimal>> GetTotalExpr()
{
return x => x.QuoteTotal;
}
}
我尝试了各种方法,但是如果不引入魔法字符串,我就无法使其工作,ala x.GroupBy("InvoiceTotal")
。
据我所知,这些东西很难,因为在将泛型“渲染”为“具体类型”之前,LINQ类型已得到解决。但是,所有类型的签名在编译时都是已知的,所以我似乎应该能够强制编译器去做。