You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带Lambda表达式参数的泛型方法作为委托传递?

当然可以实现!这里有两种清晰的解决方案

你的核心需求是在传递泛型方法作为委托时,同时携带Lambda过滤器参数——其实只需要调整委托类型或者利用闭包捕获就能搞定,下面我会结合你的代码给出具体修改方案:


先明确基础修改:让加载方法支持过滤器

首先我们需要把LoadFromDBAsync和GetAllItemsFromTableAsync调整为支持接收过滤器参数,这是后续所有逻辑的基础:

/// <summary>
/// 视图模型中的加载方法,现在支持接收过滤器
/// </summary>
protected virtual async Task<TCollection> LoadFromDBAsync<TColItemType, TCollection>(
    Expression<Func<TColItemType, bool>> filter = null)
    where TCollection : List<TColItemType>, new()
    where TColItemType : new()
{
    // 这里可以添加自定义预处理逻辑(比如权限检查、日志)
    return (TCollection)await GetAllItemsFromTableAsync<TColItemType>(filter);
}

/// <summary>
/// 数据库查询方法,现在接收过滤器并传递给底层DB方法
/// </summary>
protected async Task<List<TColItemType>> GetAllItemsFromTableAsync<TColItemType>(
    Expression<Func<TColItemType, bool>> filter = null)
    where TColItemType : new()
{
    // 准备工作、空值检查等
    return await database.GetAllWithChildrenAsync<TColItemType>(recursive: true, filter: filter);
}

方案一:修改LoadPickerAsync,直接传递过滤器和带参数的委托

这个方案更直观,适合需要在LoadPickerAsync内部访问过滤器逻辑的场景:

调整LoadPickerAsync的签名

新增过滤器参数,并把委托类型改为接收过滤器、返回异步任务的类型:

protected virtual async Task<TCollection> LoadPickerAsync<TColItemType, TViewModel, TCollection>(
    PropertyInfo collectionProperty,
    PropertyInfo indexProperty,
    PropertyInfo objectProperty,
    Expression<Func<TColItemType, bool>> filter, // 新增过滤器参数
    Func<Expression<Func<TColItemType, bool>>, Task<TCollection>> collectionLoaderAsync)
    where TCollection : List<TColItemType>
{
    // 对属性执行特殊操作(比如校验、初始化)

    // 调用加载方法并传递过滤器
    var loadedCollection = await collectionLoaderAsync(filter);
    if (loadedCollection != default(TCollection))
    {
        // 执行后续操作(比如设置加载完成标志、更新UI)
    }
    return loadedCollection;
}

在RefreshControls中调用

直接传递过滤器Lambda和LoadFromDBAsync方法作为委托:

protected async Task RefreshControls()
{
    await LoadPickerAsync<Car, ViewModel<Car>, List<Car>>(
        this.GetPropertyInfo(x => x.AvailableColors),
        this.GetPropertyInfo(y => y.ColorIndex),
        this.GetPropertyInfo(z => z.Color),
        x => x.ID == 4, // 传递Car的过滤器
        LoadFromDBAsync<Colors, List<Colors>>);

    await LoadPickerAsync<Truck, ViewModel<Truck>, List<Truck>>(
        this.GetPropertyInfo(x => x.AvailableColors),
        this.GetPropertyInfo(y => y.ColorIndex),
        this.GetPropertyInfo(z => z.Color),
        x => x.ID == 3, // 传递Truck的过滤器
        LoadFromDBAsync<Colors, List<Colors>>);
}

方案二:利用闭包捕获过滤器,保持原有LoadPickerAsync签名

如果不想修改LoadPickerAsync的原有结构,可以用闭包把过滤器绑定到委托中,传递一个无参数的委托给LoadPickerAsync:

保持LoadPickerAsync的原有签名

不需要做任何修改,还是原来的无参数委托类型:

protected virtual async Task<TCollection> LoadPickerAsync<TColItemType, TViewModel, TCollection>(
    PropertyInfo collectionProperty,
    PropertyInfo indexProperty,
    PropertyInfo objectProperty,
    Func<Task<TCollection>> collectionLoaderAsync)
    where TCollection : List<TColItemType>
{
    // 原有逻辑不变
    var loadedCollection = await collectionLoaderAsync();
    if (loadedCollection != default(TCollection))
    {
        // 执行后续操作
    }
    return loadedCollection;
}

在RefreshControls中用闭包绑定过滤器

用Lambda表达式包裹LoadFromDBAsync,把过滤器参数“打包”成无参数委托:

protected async Task RefreshControls()
{
    await LoadPickerAsync<Car, ViewModel<Car>, List<Car>>(
        this.GetPropertyInfo(x => x.AvailableColors),
        this.GetPropertyInfo(y => y.ColorIndex),
        this.GetPropertyInfo(z => z.Color),
        () => LoadFromDBAsync<Colors, List<Colors>>(x => x.ID == 4)); // 闭包捕获过滤器

    await LoadPickerAsync<Truck, ViewModel<Truck>, List<Truck>>(
        this.GetPropertyInfo(x => x.AvailableColors),
        this.GetPropertyInfo(y => y.ColorIndex),
        this.GetPropertyInfo(z => z.Color),
        () => LoadFromDBAsync<Colors, List<Colors>>(x => x.ID == 3));
}

关键知识点解释

  • 闭包:方案二中的() => LoadFromDBAsync(...)就是闭包,它会捕获x => x.ID ==4这个Lambda表达式,把带参数的方法转换成LoadPickerAsync需要的无参数委托。
  • 委托类型匹配:方案一中的Func<Expression<Func<TColItemType, bool>>, Task<TCollection>>表示“一个接收过滤器表达式、返回异步任务的方法”,正好匹配修改后的LoadFromDBAsync签名,所以可以直接传递方法名作为委托。

两种方案都能满足你的需求,选择哪一种取决于你是否需要在LoadPickerAsync内部直接访问过滤器逻辑~

内容的提问来源于stack exchange,提问作者MREme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:30:12