传递作为参数传入的谓词

Passing a predicate that was passed in as a parameter

我在将谓词传递给另一个函数时遇到问题。该谓词将作为试图调用第二个函数的参数传入。下面是一段代码。

public IEnumerable<ViewModel> BuildModel<TPart, TRecord>(Expression<Func<TRecord, bool>> predicate) 
                where TPart : ContentPart<TRecord>
                where TRecord : ContentPartRecord
            {
                IEnumerable<ReportPart> items = GetList<ReportPart, ReportRecord>(predicate);

这个问题是谓词参数,在调用 GetList() 时它一直出错,说调用有一些无效参数。获取列表调用是:

 public IEnumerable<TPart> GetList<TPart, TRecord>(Expression<Func<TRecord, bool>> predicate)
            where TPart : ContentPart<TRecord>
            where TRecord : ContentPartRecord

我一直在尝试通过多种不同的方式更改参数以使其正常工作,但我没有取得任何成功。也许我不明白为什么编译器认为 'predicate' 与 GetList() 所期望的不同。

编辑:更多信息

ReportPart : ContentPart<ReportRecord>

ReportRecord : ContentPartRecord

ContentPart 和 ContentPartRecord 都是基础 类

BuildModels 的调用者

List<ReportViewModel> model = _service.BuildReports<ReportPart, ReportRecord>(x => x.Id == 1).ToList();

构建模型

public IEnumerable<ReportViewModel> BuildReports<TPart, TRecord>(System.Linq.Expressions.Expression<Func<TRecord, bool>> predicate)
            where TPart : ContentPart<TRecord>
            where TRecord : ContentPartRecord
{
            List<ReportViewModel> model = new List<ReportViewModel>();
            IEnumerable<ReportPart> reportParts = GetList<ReportPart, ReportRecord>(predicate);
            //do some stuff with reportParts
            return model;
    }
}

获取列表

 public IEnumerable<TPart> GetList<TPart, TRecord>(System.Linq.Expressions.Expression<Func<TRecord, bool>> filter)
            where TPart : ContentPart<TRecord>
            where TRecord : ContentPartRecord
        {
            return filter == null ?
                Services.ContentManager.Query<TPart, TRecord>().List() :
                Services.ContentManager.Query<TPart, TRecord>().Where(filter).List();
        }

如果没有 a good, minimal, complete code example,就不可能确定解决您的问题的最佳方法是什么,假设存在的话。

也就是说,方差问题通常有两种形式:1) 你所做的确实是错误的,编译器正在拯救你,2 ) 你所做的并不能证明是正确的,所以你必须向编译器保证你知道你在做什么。

如果你属于第一类,那么一切都完了。你不能让它工作。

但是如果您属于第二类,您可以通过将原始谓词包装在一个与被调用方法的要求兼容的新谓词中来使您的调用正常工作:

IEnumerable<ReportPart> items =
    GetList<ReportPart, ReportRecord>(r => predicate((TRecord)r));


就是说,虽然您以这种方式编写代码可能有一些重要的原因,但考虑到您到目前为止所展示的少量代码,您并不清楚为什么您要尝试采用通用谓词并将其强制执行具体类型。

根据代码其余部分的实际情况,像这样的一对通用方法在您 1) 完全通用(即不要在对 GetList()) 或 2) 的调用中,不要强制类型为 ReportRecord 你根本不用理会泛型类型(即省略 TPartTRecord 来自 BuildModel() 方法)。

示例 1):

public IEnumerable<ViewModel> BuildModel<TPart, TRecord>(
    Expression<Func<TRecord, bool>> predicate) 
        where TPart : ContentPart<TRecord>
        where TRecord : ContentPartRecord
{
    IEnumerable<TPart> items = GetList<TPart, TRecord>(predicate);
}

例子2):

public IEnumerable<ViewModel> BuildModel(
    Expression<Func<ReportRecord, bool>> predicate)
{
    IEnumerable<ReportPart> items = GetList<ReportPart, ReportRecord>(predicate);
}

混合和匹配,即使您可以使其正常工作,也通常表明体系结构中存在更根本的问题,其中泛型要么在不应该使用的地方使用,要么没有使用受到应有的利用。


如果以上内容不能让您重回正轨,您真的应该通过提供一个最小的、完整的代码示例来改进问题。