VB.NET如何用动态拼接的条件字符串搜索对象列表?
解决动态条件搜索List(Of myObj)的问题
错误原因
你遇到的InvalidCastException是因为List(Of T).Find方法需要的是返回布尔值的委托(Predicate(Of myObj)),而你直接传入了拼接好的条件字符串。VB.NET会尝试把这个字符串转换成布尔值,显然无法完成,所以抛出了转换错误。
方案一:动态构建Predicate(推荐,类型安全+高性能)
不要用字符串拼接条件,而是通过逐步组合判断逻辑来构建匹配委托,这是最安全高效的方式:
' My vl_myObj is already filled Dim vListeAjout As New List(Of myObj) For Each Item_myObj As myObj In vl_myObj ' 初始匹配条件:默认匹配所有 Dim match As Predicate(Of myObj) = Function(c) True ' 叠加LienPartie条件 If MyCurrentRecord.Kind <> "M" And MyCurrentRecord.Kind <> "P" Then Dim targetLienPartie = Item_myObj.LienPartie match = Function(c) match(c) AndAlso c.LienPartie = targetLienPartie End If ' 叠加Equipe条件 If MyCurrentRecord.Kind = "O" Then Dim targetEquipe = Item_myObj.Equipe match = Function(c) match(c) AndAlso c.Equipe = targetEquipe End If ' 叠加其他条件... ' 执行搜索 Dim tryFindItem = vListeAjout.Find(match) ' 未找到则添加到列表 If tryFindItem Is Nothing Then vListeAjout.Add(Item_myObj) End If Next
优势
- 强类型检查,编译期就能发现错误
- 不需要额外依赖,性能远高于字符串编译方案
- 避免了字符串拼接可能出现的语法错误(比如数值转字符串的格式问题)
方案二:字符串表达式编译(仅特殊场景使用)
如果因为某些原因必须用字符串拼接条件,可以通过动态编译字符串表达式生成委托,但这种方式有安全风险(若字符串包含恶意代码)且性能较差,需谨慎使用:
步骤1:安装NuGet包
首先安装Microsoft.CodeAnalysis.VisualBasic.Scripting包,用于编译VB脚本代码。
步骤2:实现代码
Imports Microsoft.CodeAnalysis.VisualBasic.Scripting Imports Microsoft.CodeAnalysis.Scripting ' My vl_myObj is already filled Dim vListeAjout As New List(Of myObj) For Each Item_myObj As myObj In vl_myObj Dim StringFind As String = "" If MyCurrentRecord.Kind <> "M" And MyCurrentRecord.Kind <> "P" Then StringFind += " And c.LienPartie = " & Item_myObj.LienPartie End If If MyCurrentRecord.Kind = "O" Then StringFind += " And c.Equipe= " & Item_myObj.Equipe End If ' 处理开头多余的"And" If String.StartsWith(StringFind, " And ", StringComparison.OrdinalIgnoreCase) Then StringFind = StringFind.Substring(4).Trim() End If ' 无条件时默认匹配所有 If String.IsNullOrEmpty(StringFind) Then StringFind = "True" End If ' 构建脚本代码,生成匹配函数 Dim scriptCode = $"Function Match(c As myObj) As Boolean Return {StringFind} End Function" ' 配置脚本选项,引用当前程序集以识别myObj类型 Dim scriptOptions = ScriptOptions.Default.AddReferences(GetType(myObj).Assembly) ' 编译并获取委托(注意:如果是同步代码,可改用RunAsync并等待结果) Dim matchFunc = Await VisualBasicScript.EvaluateAsync(Of Predicate(Of myObj))(scriptCode, scriptOptions) ' 执行搜索 Dim tryFindItem = vListeAjout.Find(matchFunc) ' 未找到则添加到列表 If tryFindItem Is Nothing Then vListeAjout.Add(Item_myObj) End If Next
内容的提问来源于stack exchange,提问作者baronming
相关产品推荐
相关产品推荐

