如何在一组通用 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 类型在泛型“渲染”为“具体类型”之前就已解决。但是,所有类型签名在编译时都是已知的,因此我应该能够强制编译器执行此操作。