【问题标题】:Can I generate an async method dynamically using System.Linq.Expressions?我可以使用 System.Linq.Expressions 动态生成异步方法吗?
【发布时间】:2014-08-06 02:26:28
【问题描述】:

我知道编译器无法将异步 lambda 表达式转换为表达式树,但是否可以手动生成表达式树?

var expr = Expression.Lambda<Func<Task>>(
     // how do I use 'await' in the body here?
);
var func = expr.Compile();

我在Expression 类中找不到任何与async 或await 相关的方法,但也许还有其他方法?

【问题讨论】:

    标签: c# linq async-await code-generation expression-trees


    【解决方案1】:

    await 涉及重要编译器重写;生成的 IL 与原始 C# 完全不同,具有变量提升(到类上)和分支、任务、延续等。它当然不是可以用 simple lambda 表示的东西,尽管在最新版本的 .NET 中具有更丰富的 Expression 支持(Expression.Block 等),技术上我想可能可以模仿编译器为 await 所做的大部分事情 - 但你尝试手动操作可能会变得很疯狂。

    不,AFAIK,Expression API 中没有自动化这种翻译的工具,坦率地说,我没想到会有。

    ILGenerator 可能也是如此;坦率地说,AFAIK 在元编程中使用 await 的唯一“简单”方式(我使用“简单”这个词非常错误)是生成 C# 并通过 roslyn 或 CSharpCodeProvider 运行它。

    【讨论】:

    • 谢谢马克。不幸的是,使用 Roslyn 或 CSharpCodeProvider 对我来说不是一个选择。我正在开发一个 Windows 应用商店应用程序,并且该平台(AFAIK)上唯一可用的代码生成机制是 Linq 表达式。我想我将不得不改变我的方法以避免异步代码。
    • @ThomasLevesque 或其他选择当然是拥抱瞬时性,也许编写一个开源库来完成所有Expression.Block 工作以使其工作。然而,我怀疑即使这样也不够,而且它完全超出了Expression API 能够表示的范围。
    • 好吧,如果我无聊的话,也许有一天我会试一试;)
    • 我怀疑它可以做到,仅仅是因为应用于 async/await 的转换类似于自定义迭代器 (yield),并且构建在 System.Linq.Expressions 之上的 DLR 能够生成那种代码。不过,这将是不小的工作量。 OP 最好使用Task.ContinueWith() 代替await。
    • 有替代的表达式树实现(FastExpressionCompiler),在那里你可以帮助实现对async-await的支持github.com/dadhi/FastExpressionCompiler/issues/47
    猜你喜欢
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 2022-12-09
    相关资源
    最近更新 更多