c# - 如何在没有 Roslyn 的情况下将 Property1.Property2 之类的路径评估为已编译的表达式
问题描述
在我的 blazor webassembly 应用程序中,我想评估字符串路径,例如:
"Property1.Property2"
- 可选
Property1[index]
和Property1["key"]
- 可选
Method1().Property2
要求是:
- 我能够以某种方式编译/缓存表达式并使用不同的参数(参数=源对象)多次评估它。速度很重要
- 我需要评估路径以获得价值
- 如果路径指向属性,我需要能够设置值。
- 我需要能够获取 MemberInfo,尽管这可以使用不同的评估器在外部完成。
我不需要像这样评估数学表达式Property1 * Property2
我有什么
我使用过 RoslynAPI,类似于:
var discountFilter = "album => album.Quantity > 0";
var options = ScriptOptions.Default.AddReferences(typeof(Album).Assembly);
Func<Album, bool> discountFilterExpression = await CSharpScript.EvaluateAsync<Func<Album, bool>>(discountFilter, options);
var discountedAlbums = albums.Where(discountFilterExpression)
但我不能在我的 Blazor WebAssembly 应用程序中使用 Roslyn,因为它太重了。
是否有一种更轻量级的评估路径的方法,最好是构建表达式?
解决方案
我还没有专门为 WASM 测试过它,但是表达式树可能是你的朋友——但是,没有神奇的“解析这个字符串”按钮;但假设您有自己的字符串解析器,您将希望最终检查 AST 并构造Expression
类似于:
// constructs: (Album album) => album.Quantity > 0
var p = Expression.Parameter(typeof(Album), "album");
var body = Expression.GreaterThan(
Expression.PropertyOrField(p, "Quantity"),
Expression.Constant(0, typeof(int)));
var lambda = Expression.Lambda<Func<Album, bool>>(body, p);
然后,您可以通过以下方式获取可重用委托:
Func<Album, bool> func = lambda.Compile();
在设置值方面:这也很好:Expression.Assign
在一个Expression.Block
可以再次编译的内部。
然而!在 WASM 上,我怀疑它Compile()
会使用解释而不是 ref-emit,这意味着它可能只是在底层使用反射(PropertyInfo.SetValue
等),而不是任何更原生的东西。
推荐阅读
- javascript - 如何下载当前计算机/磁盘上的文件?注意:我有一个其他计算机可以连接的本地 IP - node.js
- sql - SQL - 是否可以从“SELECT”子句中排除列?
- python - 如何在熊猫中快速计算多个假期日历中两个日期列之间的工作日数?
- powershell - 为什么 appcmd.exe 不允许设置 ipSecurity allowUnlisted?
- android - 如何修复proguard?无法使用 proguard 构建签名的 apk
- html - 在 React Bootstrap 中居中对齐 NavItem
- maven - 如何使用 jmeter maven 插件运行特定的 jmx 文件
- php - 如何让 PHP 回显到 jQuery 弹出警报?
- java - Spring Boot org.springframework.web.util.NestedServletException:请求处理失败
- php - 我的 php 文件不输出,而是显示源文件