如何将 Expression<T, bool> where TO : Custom Class 存储到 Expression<CustomClass, bool> 属性 中?

How can I store an Expression<T, bool> where T : CustomClass into an Expression<CustomClass, bool> property?

此问题与 的上下文相同。我正在复制粘贴说明部分,因为它与两者都相关:

我们有一个项目使用遗留数据库,EntityFramework 无法使用。

所以我们已经开始构建一个穷人 EntityFramework,其基础 class CustomBaseTable 实体 class 是从中派生出来的。另一个 class、CustomQueryBuilder 具有构建 SQL 查询的方法:BuildSelectQuery(CustomBaseTable p_objEntity) 等等。

我们的第一个版本可以很好地构建查询,但是我们使用的是相当粗糙的对象,这些对象并不是很灵活(为了保存细节而保留 space)。

我最近意识到使用 Expression 个对象会更加高效和灵活。

所以我想向 CustomBaseTable 添加一个方法,它的工作方式或多或少类似于 Where():

    EntityTable z_objEntity = new EntityTable();
    z_objEntity.CustomWhere(t => t.Field1 == Value1);
    CustomQueryBuilder z_objBuilder = new CustomQueryBuilder(DBTypeEnum.DataBaseType);
    string z_strQuery = z_objBuilder.BuildSelectQuery(z_objEntity);

结束说明。

我希望 CustomWhere() 将该表达式存储在 属性 中,并在 BuildSelectQuery(CustomBaseTable p_objEntity) 中使用后者以将其解析为敏锐的 SQL Where 子句。 (当然,它会在 UpdateDelete 查询也会使用的单独方法中发生。)

我在CustomBaseTable中写了一个属性:

        public Expression<Func<CustomBaseTable, bool>> WhereClauseExpression

所以CustomWhere()应该做类似

的事情
        public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
        {
            z_objTable.WhereClauseExpression = p_expWhereClause;
        }

但是,作为 Expression<Func<T, bool>> 对象的 p_expWhereClause 无法转换为 Expression<Func<CustomBaseTable, bool>>

我尝试创建一个 ICustomBaseTableCustomBaseTable 从中派生并使 WhereClauseExpression 成为 Expression<Func<ICustomBaseTable, bool>>,结果相同。

受到this question的启发,我尝试了

            z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);

同样,转换失败。

我认为如果不在 CustomBaseTable<T> 中声明 T,我无法将 WhereClauseExpression 设为 Expression<Func<T, bool>>,我也不想要。

当然,解决方法是在CustomQueryBuilder中有一个方法,将表达式解析为Where子句,然后将后者存储在WhereClause String 属性,但我宁愿一次生成所有 SQL 代码;它让我觉得更干净。

有没有办法将 Expression 存储到 属性 中,这对任何派生的 class 都有效?

最后,答案是:我做不到……不过没关系。

如题中所说,我试过了

        public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
        {
            z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);
        }

还是不行,因为Parameters中的参数类型是T,而不是CustomBaseTable

所以经过一些摆弄后,CustomWhere() 现在看起来像

        public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
        {
            z_objTable.WhereClauseExpression = Expression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters.Select(p => Expression.Parameter(typeof(CustomBaseTable), p.Name)));
        }

不仅转换工作完美,而且更好的是,z_objTable.WhereClauseExpression 中的 Expression 个对象,从 Body 开始,使用 T 个对象而不是 CustomBaseTable。我需要的是子表达式使用 T,这就是我最后得到的。