如何修改Expression>的类型参数?

2023-11-22

我有一个以下的例子:

Expression<Func<IRequiredDate, bool>>

我希望将其转换为以下实例,以便它可以用于在实体框架中运行查询:

Expression<Func<TModel, bool>>

这将允许我对任何实现 IRequiredDate 的模型使用通用过滤查询,例如:

// In some repository function:
var query = DbContext.Set<Order>()
     .FilterByDateRange(DateTime.Today, DateTime.Today);

var query = DbContext.Set<Note>()
     .FilterByDateRange(DateTime.Today, DateTime.Today);

var query = DbContext.Set<Complaint>()
     .FilterByDateRange(DateTime.Today, DateTime.Today);


// The general purpose function, can filter for any model implementing IRequiredDate
public static IQueryable<TModel> FilterByDate<TModel>(IQueryable<TModel> query, DateTime startDate, DateTime endDate) where TModel : IRequiredDate
{
    // This will NOT WORK, as E/F won't accept an expression of type IRequiredDate, even though TModel implements IRequiredDate
    // Expression<Func<IRequiredDate, bool>> dateRangeFilter = x => x.Date >= startDate && x.Date <= endDate;
    // query = query.Where(dateRangeFilter);

    // This also WON'T WORK, x.Date is compiled into the expression as a member of IRequiredDate instead of TModel, so E/F knocks it back for the same reason:
    // Expression<Func<TModel, bool>> dateRangeFilter = x => x.Date >= startDate && x.Date <= endDate;
    // query = query.Where(dateRangeFilter);

    // All you need is lov.... uh... something like this:
    Expression<Func<IRequiredDate, bool>> dateRangeFilter = x => x.Date >= startDate && x.Date <= endDate;
    Expression<Func<TModel, bool>> dateRangeFilterForType = ConvertExpressionType<IRequiredDate, TModel>(dateRangeFilter); // Must convert the expression from one type to another
    query = query.Where(dateRangeFilterForType) // Ahhhh. this will work.

    return query;
}

public static ConvertExpressionType<TInterface, TModel>(Expression<Func<TInterface, bool>> expression)
where TModel : TInterface // It must implement the interface, since we're about to translate them
{
    Expression<Func<TModel, bool>> newExpression = null;

    // TODO: How to convert the contents of expression into newExpression, modifying the
    // generic type parameter along the way??

    return newExpression;
}

我知道它们是不同的类型,不能进行转换。不过我想知道是否有办法创建一个新的Expression<Func<TModel, bool>>,然后根据内容重建它Expression<Func<IRequiredDate, bool>>提供,切换任何类型引用IRequiredDate to TModel正在进行中。

这可以做到吗?


所以实际进行映射的方法不是that很难,但遗憾的是我没有找到一个很好的方法来概括它。这是一个方法,需要一个Func<T1, TResult>并将其映射到一个委托,其中参数比T1:

public static Expression<Func<NewParam, TResult>> Foo<NewParam, OldParam, TResult>(
    Expression<Func<OldParam, TResult>> expression)
    where NewParam : OldParam
{
    var param = Expression.Parameter(typeof(NewParam));
    return Expression.Lambda<Func<NewParam, TResult>>(
        expression.Body.Replace(expression.Parameters[0], param)
        , param);
}

这使用了Replace方法将一个表达式的所有实例替换为另一个表达式的所有实例。定义是:

internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}

现在我们可以使用这个方法(应该给它一个更好的名字),如下所示:

Expression<Func<object, bool>> oldExpression = whatever;
Expression<Func<string, bool>> newExpression =
    Foo<string, object, bool>(oldExpression);

当然,自从Func实际上就其参数而言是协变的,我们可以确定对此方法的任何调用都会生成不会添加运行时故障点的表达式。

你可以简单地制作这个版本Func<T1, T2, TResult>,依此类推,直到 16 种不同类型Func如果您愿意,只需为每个参数创建一个参数表达式,然后用新的替换所有旧的。这会很乏味,但只要遵循模式即可。鉴于新旧参数类型都需要有一个通用参数,并且无法推断参数,这会变得……混乱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何修改Expression>的类型参数? 的相关文章

随机推荐

  • 拥有 MSI 安装包的主要优势是什么?

    我以为这会在网络上的某个地方 但我无法用谷歌搜索它 考虑到创建 MSI 包的复杂性 与 NSIS InnoSetup 等相比 什么是一个令人信服的理由去经历所有这些混乱 使用 MSVS 蹩脚的安装项目向导 学习一个全新的语言 生态系统只是为
  • json 键作为数字

    我有一个 JSON 传递给脚本 我不知道 JSON 键 因为它们是动态的 实际上 它们是数字 这就是我得到的 var countries 223 142 143 222 23 26 25 24 170 1 2 我尝试像这样访问数据 var
  • random() 函数内部 - 它是如何实现的?

    我们通常使用 random 函数在 C 中创建随机数 使用 void srand 无符号整数种子 可以改善结果 因为它会根据种子的值生成随机数 谁能告诉我随机函数是如何实际实现的 Here是 GNU C 库的 random 函数中使用的算法
  • Git - 包超出允许的最大大小

    我正在处理大量的二进制文件 最近对本地 git 存储库进行更改后 我尝试将更改推送回远程 结果收到以下错误 remote fatal pack exceeds maximum allowed size 不幸的是我无法使用所描述的策略here
  • Python:生成具有趋势的随机时间序列数据(例如周期性、指数衰减等)

    我正在尝试生成一些具有趋势的随机时间序列 例如周期性 例如销售 指数下降 例如帖子上的 Facebook 点赞数 指数增长 例如比特币价格 普遍增加 股票行情 等 我可以生成普遍增加 减少时间序列如下 import numpy as np
  • TextView 具有不同的字体和样式?

    是否可以在同一文本中包含不同大小 字体类型或样式的文本TextView 像这样的东西 myLogin logout 您可以使用以下方法执行此操作 textView setText Html fromHtml b myLogin b i lo
  • UICollectionView:必须使用非零布局参数进行初始化

    I added UICollectionView通过代码 现在 应用程序崩溃并显示消息 UICollectionView must be initialized with a non nil layout parameter 你有什么想法来
  • 如何将适用于 Windows 的 PHP 5.3 扩展编译为 DLL?

    我目前正在重写一个PHP最初编写的扩展PHP 4 2 2 我的问题是让构建 编译过程生成一个 dll而不是将扩展编译到PHP核 环境是windows server 2003 我使用的是Visual Studio 2008 我使用 EXT S
  • JS:函数参数默认值

    在某些语言中 您可以为函数的参数设置默认值 function Foo arg1 50 arg2 default 你如何在 JavaScript 中做到这一点 在 JavaScript 中 任何未设置的内容都会被赋予值undefined 这意
  • fputs( _("") ) 下划线代表什么?

    我终于开始看一些 Linux 代码 我现在正在看ls c 在函数usage 在底部我发现了很多这样的说法 fputs List information about the FILEs the current directory by def
  • TFS 构建错误 - “指定的路径、文件名或两者都太长...”

    我正在编写构建过程模板的自定义活动 我在构建活动时遇到以下问题 gt XamlBuildTask error XC1043 Extension Microsoft Activities Build BeforeInitializeCompo
  • 通过 API 调用获取文件(R 和管道工)

    我使用管道工作为一些 R 函数的简单 Web API 服务 我想通过 R 函数提供一个文件 下载 在客户端 非常像Flask 在 python 中通过 send file 和 send from directory 执行此操作 I trie
  • 将源代码附加到 Jprofiler

    我刚开始使用 JProfiler 我正在对应用程序进行远程分析 当我单击任何对象的显示源时 它显示 在源路径中找不到源文件 因为远程计算机上只有二进制文件 有什么办法可以链接源代码吗 仅供参考 我可以访问我可以使用的代码 在 JProfil
  • 使命名的锚点书签在单击时始终显示在屏幕顶部

    我的标记如下 li a href sheds housing Sheds amp Housing a li div h1 sheds amp housing h1 img src images cattle sheds housing pn
  • 如何循环访问 boost::mpl::list?

    据我所知 这是 include
  • 检测 adblock 和 javascript [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我希望检测我网站上的广告拦截软件 并要求用户通过重定向禁用广告拦截 我发现的唯一方法是使用 Javascript 还有其他检测方法吗 如果没有 我如何检测 Javascript
  • 使用 Javascript 正则表达式检测行尾或字符串结尾

    我试图找到 Javascript 正则表达式来检测关键字 任何字符 后跟新行或字符串结尾 这是我的尝试 n 我不确定 可以用在 or 条件中 有什么想法吗 UPDATE 我试图用正则表达式检测的是一个关键字 后跟 1 另一个关键字 或 2
  • Java UIManager 键列表

    我见过人们使用 UIManager 来更改一些预先创建的 swing 组件 例如 JFileChooser 的字符串 我在哪里可以找到某种参考来告诉我哪些组件中的哪些字符串是可以更改的 以及如何访问它们 澄清 我知道UIManager pu
  • 处理 (jQuery) Ajax 调用中返回的 ASP.NET MVC FileResult

    Goal 我想让我的用户在我的网页上下载文件 我想要打开一个新窗口 并在其中显示或下载文件 我的实现 然而 该文件首先必须在服务器端生成 这可能需要一段时间 当用户单击按钮下载文件时 我会执行 ajax 调用并显示等待动画 直到收到响应 处
  • 如何修改Expression>的类型参数?

    我有一个以下的例子 Expression