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

如何在返回Expression的C#方法中调用返回Func<>的方法

原有实现
public static System.Linq.Expressions.Expression<Func<MetaMovie, bool>> IsEqual(MetaMovie other)
{
    if (other.Id > 0) return m => other.Id == m.Id;

    return m => other.MetaSource == m.MetaSource && other.ExternalId == m.ExternalId;
}

调用上述方法后变量的DebugView内容:

.Lambda #Lambda1<System.Func`2[com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie,System.Boolean]>(com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie $m)
{
    (.Constant<com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie+<>c__DisplayClass81_0>(com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie+<>c__DisplayClass81_0>).other).MetaSource ==
    $m.MetaSource && (.Constant<com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie+<>c__DisplayClass81_0>(com.cyberinternauts.all.MediaRecognizer.Models.Metas.MetaMovie+<>c__DisplayClass81_0>).other).ExternalId ==
    $m.ExternalId
}
需求目标

希望创建一个Func<MetaMovie, bool> GetComparison(MetaMovie other)方法,供IsEqual方法调用,但无法成功集成。

尝试的实现
public static Func<MetaMovie, bool> GetComparison(MetaMovie other)
{
    if (other.Id > 0) return m => other.Id == m.Id;

    return m => other.MetaSource == m.MetaSource && other.ExternalId == m.ExternalId;
}

public static Expression<Func<MetaMovie, bool>> IsEqual(MetaMovie other)
{
    var param1 = Expression.Parameter(other.GetType(), "param1");

    return Expression.Lambda<Func<MetaMovie, bool>>(Expression.Call(GetComparison(other).Method), param1);
}
遇到的错误

IsEqual方法的return行报错:
Static method requires null instance, non-static method requires non-null instance


错误原因与解决方法

错误本质是:你试图直接调用匿名委托的Method属性,但这些匿名方法是绑定到捕获变量的显示类实例的实例方法,调用时必须传入对应的实例作为第一个参数;更关键的是,这种方式会破坏表达式树的可解析性(比如EF无法翻译该表达式执行数据库查询)。

方案一:让GetComparison返回表达式树(推荐)

直接修改GetComparison返回表达式树,这样IsEqual可以直接复用其结果,完全保留原有逻辑的表达式树特性:

public static Expression<Func<MetaMovie, bool>> GetComparison(MetaMovie other)
{
    if (other.Id > 0) 
        return m => other.Id == m.Id;

    return m => other.MetaSource == m.MetaSource && other.ExternalId == m.ExternalId;
}

public static Expression<Func<MetaMovie, bool>> IsEqual(MetaMovie other)
{
    return GetComparison(other);
}

方案二:必须返回委托时,手动构建表达式树

如果业务限制必须让GetComparison返回编译后的委托,那么需要在IsEqual中手动构建等价的表达式树,避免直接调用委托方法:

public static Func<MetaMovie, bool> GetComparison(MetaMovie other)
{
    if (other.Id > 0) return m => other.Id == m.Id;

    return m => other.MetaSource == m.MetaSource && other.ExternalId == m.ExternalId;
}

public static Expression<Func<MetaMovie, bool>> IsEqual(MetaMovie other)
{
    var param = Expression.Parameter(typeof(MetaMovie), "m");
    Expression body;

    if (other.Id > 0)
    {
        var otherId = Expression.Constant(other.Id);
        var paramId = Expression.Property(param, nameof(MetaMovie.Id));
        body = Expression.Equal(otherId, paramId);
    }
    else
    {
        var otherMetaSource = Expression.Constant(other.MetaSource);
        var paramMetaSource = Expression.Property(param, nameof(MetaMovie.MetaSource));
        var sourceEqual = Expression.Equal(otherMetaSource, paramMetaSource);

        var otherExternalId = Expression.Constant(other.ExternalId);
        var paramExternalId = Expression.Property(param, nameof(MetaMovie.ExternalId));
        var idEqual = Expression.Equal(otherExternalId, paramExternalId);

        body = Expression.AndAlso(sourceEqual, idEqual);
    }

    return Expression.Lambda<Func<MetaMovie, bool>>(body, param);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:15:33