使用表达式树的 Foreach 循环

2023-12-27

我见过这个构建动态表达式树时出现问题 https://stackoverflow.com/questions/3646283/issue-while-building-dynamic-expression-tree and 表达式/语句树 https://stackoverflow.com/questions/1936525/expression-statement-trees由于我是表达树的新手,我仍然在努力理解如何实现我想要的。

下面是一个人为的对象

    public class TestObject
    {
        public TestObject()
        {
            ClassList = new List<Class>();
        }
        public int Age { get; set; }
        public List<Class> ClassList { get; set; } 
    }

    public class Class
    {
        public string Name { get; set; }
        public int ClassId { get; set; }
    }

在运行时,我迭代每个属性并生成一个委托,该委托将转换为该属性的字符串。我已经把所有的工作都做好了。我现在必须处理的问题是,对于 List 类型,我需要能够对 ClassList 属性中的每个项目应用一组操作,因此我需要一个 foreach 来允许我执行此操作。

我目前有这个

//type==TestObject at runtime
//propertyName == "ClassList"
   ParameterExpression recordExpression = Expression.Parameter(type, "record");

   memberExpression = MemberExpression.Property(recordExpression, propertyName);

   Type getEnumerableDelegateType =
                typeof(Func<,>).MakeGenericType(new Type[] { type, memberExpression.Type}); 

   var getList = Expression.Lambda(getEnumerableDelegateType, memberExpression, recordExpression);

GetList 在编译和调用时会按预期返回 List。我正在努力解决的是如何创建一个表达式,该表达式将使用 lambda 表达式的结果,并应用我已经为每个类项创建的操作集对其进行迭代。

最终我正在寻找一个 lambda 签名来匹配整体行动下面签名

   var getListFunc = new Func<TestObject, List<Class>>((TestObject obj1) => obj1.ClassList);

   Action<List<Class>> listAction = delegate(List<Class> data)
                {
                    foreach (var dataChannelWithUnitse in data)
                    {
                        //Apply generated delegate
                    }
                };

     Action<TestObject> overallAction = delegate(TestObject data)
                {
                    var x = getListFunc.Invoke(data);
                    listAction.Invoke(x as List<Class>);
                };

感谢任何帮助我了解如何做到这一点的帮助。

我目前已经得到了这个例外从范围“”引用了“TestObject”类型的变量“Input”,但未定义

    var typeParam = Expression.Parameter(type, "Input");
    var listVariable = Expression.Variable(memberExpression.Type, "List");
    var enumerator = Expression.Variable(typeof(IEnumerator<>).MakeGenericType(dataType));


    var enumeratorType = typeof(IEnumerator<>).MakeGenericType(dataType);
    var enumerableType = typeof(IEnumerable<>).MakeGenericType(dataType);
    var enumerableParam = Expression.Parameter(enumerableType, "ExtractedCollection");

    var getEnumeratorFunc = Expression.Call(enumerableParam, enumerableType.GetMethod("GetEnumerator"));
    var getEnumeratorLambda = Expression.Lambda(getEnumeratorFunc, enumerableParam);

    var t1 = Expression.Assign(listVariable, Expression.Invoke(getListLambda, typeParam));
    var t2 = Expression.Assign(enumerator, Expression.Invoke(getEnumeratorLambda, listVariable));


    var @break = Expression.Label();

    var funcBlock = Expression.Block(
        new ParameterExpression[] { listVariable, enumerator},

   t1,
   t2,

    Expression.Loop(
        Expression.IfThenElse(

            Expression.NotEqual(Expression.Call(enumerator,typeof(IEnumerator).GetMethod("MoveNext")),Expression.Constant(false)),
                                Expression.Invoke(enumerableExpressions[0],Expression.Property(enumerator, "Current")),

                      Expression.Break(@break))
            , @break), typeParam);



    Expression<Action<TestObject>> lm = Expression.Lambda<Action<TestObject>>(funcBlock,recordExpression);
    var d = lm.Compile(); **//this is exceptioning with " variable 'Input' of type 'TestObject' referenced from scope '', but it is not defined**

我在你的问题中迷失了方向(如果我解释错误,请告诉我,我会再深入探讨),但我think这就是你所追求的:

public static Expression ForEach(Expression collection, ParameterExpression loopVar, Expression loopContent)
{
    var elementType = loopVar.Type;
    var enumerableType = typeof(IEnumerable<>).MakeGenericType(elementType);
    var enumeratorType = typeof(IEnumerator<>).MakeGenericType(elementType);

    var enumeratorVar = Expression.Variable(enumeratorType, "enumerator");
    var getEnumeratorCall = Expression.Call(collection, enumerableType.GetMethod("GetEnumerator"));
    var enumeratorAssign = Expression.Assign(enumeratorVar, getEnumeratorCall);

    // The MoveNext method's actually on IEnumerator, not IEnumerator<T>
    var moveNextCall = Expression.Call(enumeratorVar, typeof(IEnumerator).GetMethod("MoveNext"));

    var breakLabel = Expression.Label("LoopBreak");

    var loop = Expression.Block(new[] { enumeratorVar },
        enumeratorAssign,
        Expression.Loop(
            Expression.IfThenElse(
                Expression.Equal(moveNextCall, Expression.Constant(true)),
                Expression.Block(new[] { loopVar },
                    Expression.Assign(loopVar, Expression.Property(enumeratorVar, "Current")),
                    loopContent
                ),
                Expression.Break(breakLabel)
            ),
        breakLabel)
    );

    return loop;
}

要使用它,您需要提供一个要迭代的集合、一个要替换到循环体中的表达式,以及一个由循环体表达式使用的 ParameterExpression,它将在每次循环迭代时分配给循环变量。

我认为有时候例子胜于雄辩......

var collection = Expression.Parameter(typeof(List<string>), "collection");
var loopVar = Expression.Parameter(typeof(string), "loopVar");
var loopBody = Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), loopVar);
var loop = ForEach(collection, loopVar, loopBody);
var compiled = Expression.Lambda<Action<List<string>>>(loop, collection).Compile();
compiled(new List<string>() { "a", "b", "c" });

编辑:正如杰罗姆·莫斯特在评论中正确指出的那样,这并不quite镜像 foreach 循环的“真实”行为:这将确保它处理枚举器。 (它还会为每次迭代创建循环变量的新实例,但这对于表达式没有意义)。如果您有足够的动力,那么实现这一点只需转动手柄即可!


对于在家观看的人,我有一个类似的方法来生成“for”循环:

public static Expression For(ParameterExpression loopVar, Expression initValue, Expression condition, Expression increment, Expression loopContent)
{
    var initAssign = Expression.Assign(loopVar, initValue);

    var breakLabel = Expression.Label("LoopBreak");

    var loop = Expression.Block(new[] { loopVar },
        initAssign,
        Expression.Loop(
            Expression.IfThenElse(
                condition,
                Expression.Block(
                    loopContent,
                    increment
                ),
                Expression.Break(breakLabel)
            ),
        breakLabel)
    );

    return loop;
}

这相当于以下语句,其中伪变量与上述方法中的表达式匹配:

for (loopVar = initValue; condition; increment)
{
    loopContent
}

同样,loopContent、condition 和increment 是使用loopVar 的表达式,并且loopVar 在每次迭代时分配。

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

使用表达式树的 Foreach 循环 的相关文章

  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 引用的程序集自动由 Visual Studio 替换

    我有 2 个项目 一个可移植类库和一个常规单元测试项目 在可移植类库中 我使用 NuGet 来引用 Microsoft BCL 可移植包 它附带 2 个程序集 System Threading Tasks dll and System Ru
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么

随机推荐

  • 如何在不刷新页面的情况下自动提交此表单?

    这一切都在一个 php 文件中
  • Go 中的单例

    如何在Go语言中实现单例设计模式 抛开实现单例模式是否是个好主意的争论 下面是一个可能的实现 package singleton type single struct O interface var instantiated single
  • Java从int到字节错误的可能有损转换[重复]

    这个问题在这里已经有答案了 当我从 jar 文件中反编译一些类时 就会发生这种情况 这些是我唯一无法克服的错误 所有这些错误都是 可能是从 int 到 byte 的有损转换 this onDemandFetcher method563 1
  • 如何从脚本而不是终端使用 PyInstaller?

    简洁版本 如何从 Python 脚本中而不是从终端使用 PyInstaller 我需要在 Python 脚本中编写什么才能获得与在终端中编写的等效内容 gt python m PyInstaller noconsole name WorkL
  • 无法执行Findbugs 原因:该项目包含未编译的Java源文件

    我目前正在使用 sonarqube 服务器 5 6 和扫描仪 2 6 1 并且在分析 java 项目期间不断收到错误 它似乎抱怨一些未在二进制文件夹中编译的 java 文件 二进制文件夹中根本没有任何文件 添加 X 参数后 我会收到更多异常
  • 如何在 C++ 中使用 yahoo 或 gmail 发送电子邮件

    我想在我的 C 程序中发送一封电子邮件 看起来有点复杂 有没有办法使用 yahoo 或 gmail 来发送我的电子邮件 基本的互联网search http www vmime org 揭示了以下内容 C SMTP 示例 https stac
  • C++中有没有像.Net中的反射器这样的概念?

    我喜欢从 c dll 获取代码 我知道我们可以通过反射器轻松从 Net dll 获取代码 c 中有没有可用的方法 提前致谢 C 直接编译为机器代码 没有像 NET 那样的中间语言 有你可以看一下 Hex Rays 反编译器 http www
  • 如何找出 JVM 对我的代码应用了哪些优化?

    JVM 尤其是 HotSpot VM 因可在运行时应用大量优化而闻名 有没有办法查看某段代码并了解 JVM 实际上对其做了什么 一个问题是 JVM 实际对它做了什么 在调用之间发生变化 因为 JVM 可以自由地重新生成代码 举个例子 几天前
  • Delphi:类似 FireFox 中的 AnimateWindow

    我有一个面板 底部对齐 和一些控件 客户端对齐 为了使面板动画化 我使用 AnimateWindow Panel Handle 1000 aw hide or AW SLIDE OR AW VER POSITIVE panel Visibl
  • InvalidDefinitionException:找不到内部类的序列化器

    我有这门课 我想返回RestAPI打电话进来JSON format return ResponseEntity ok cacheControl CacheControl maxAge 5 TimeUnit MINUTES body hote
  • Gradle 构建在全新安装和空项目上永久运行

    Gradle 构建永远运行 我不明白为什么 我在 Ubuntu 15 04 上安装了 Android Studio 它使用向导中的所有默认选项进行设置 我创建了一个空项目 没有添加任何代码 当我尝试构建项目时 gradle 进程会启动但永远
  • 如何获得 2 个表的结果

    我有 2 张桌子 一种叫booking 另一种叫room Booking 中的列为 RoomID startdate enddate customerId 房间中的列是 RoomID 大小 我想从预订表中选择一行 其中日期位于开始日期和结束
  • 尝试在集群上无头运行 NetLogo 时出现 Java 错误

    我正在尝试使用 Linux 无头运行 Netlogo 以便将作业发送到集群 我以前从未使用过 Linux 但我正在尝试按照此处的说明进行操作 http netlogo users 18673 x6 nabble com Running Ne
  • FlushViewOfFile (Windows) 和 msync(Linux) 的时间消耗

    我们感兴趣的是时间消耗FlushViewOfFile https learn microsoft com en us windows win32 api memoryapi nf memoryapi flushviewoffile and
  • Scala 过滤器元组 (x, y) == (y, x)

    我有一个元组列表 例如 0 2 0 5 2 0 2 5 3 4 4 3 5 0 5 2 有一些元组在哪里 x y y x 例如 5 0 和 0 5 我只想留下其中一个 例如第一个 我该怎么做 使用左折叠 var ts List 0 2 0
  • Python 中真正的非阻塞 HTTPS 服务器

    我正在尝试用 Python 构建一个真正的非阻塞 HTTPS 服务器 如果每个人都玩得很好 下面的最小代码就可以正常工作 import BaseHTTPServer import SimpleHTTPServer import Socket
  • Python struct.pack 和 unpack

    我绝不是一个经验丰富的Python程序员 这就是为什么我相信这个问题可能有一个明显的答案 但我就是无法理解struct pack和unpack 我有以下代码 struct pack lt I elements self buf elemen
  • Android Compose 导航和 ViewModel 生命周期

    我刚刚开始使用 Compose 对于我来说 第一眼看上去 它就像是我喜欢的 SwiftUI 的副本 但当我真正开始使用它时 我很快就遇到了很多问题 显然 我需要找到如何使用它才能从中受益的正确方法 这是我的问题之一 package org
  • 确定 STDERR 是否要终端

    我有一套 Java 程序 它们在我们的 Linux 服务器上用作命令行工具 他们中的大多数使用一个在 STDERR 上打印进度条的类 类似于 Perl 的Term ProgressBar 我希望每当 STDERR 进入终端时显示进度条 并在
  • 使用表达式树的 Foreach 循环

    我见过这个构建动态表达式树时出现问题 https stackoverflow com questions 3646283 issue while building dynamic expression tree and 表达式 语句树 ht