通用C#LINQ聚合而不依赖于动态ExpressionBuilder

时间:2017-02-10 16:57:01

标签: c# linq generics dry expressionbuilder

如何在一组通用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类型已得到解决。但是,所有类型的签名在编译时都是已知的,所以我似乎应该能够强制编译器去做。

0 个答案:

没有答案