VB.Net中NameOf运算符逆向实现:批量构建常量字典需求
VB.NET中实现字符串到常量的逆向映射(批量构建常量字典)
在VB.NET开发场景中,当需要基于大量命名有规律的字符串常量构建可通过名称检索的字典时,手动编写{{NameOf(CONST_FEN01), CONST_FEN01}, ...}这类初始化代码效率极低。若已能生成常量名称字符串数组,可通过以下几种方案实现字符串到常量值的逆向映射,自动完成字典构建:
方案1:运行时反射实现
常量在编译后会被转换为类的静态只读字段,可通过反射获取字段值,实现字符串到常量的映射。
步骤1:修正常量名称生成代码
确保生成的名称与常量定义完全匹配(需包含CONST_前缀):
Function BuildNamesArray(ByVal prefix As String, ByVal count As Integer) As String() Dim names As New List(Of String)() For i As Integer = 1 To count names.Add($"{prefix}{i}") Next Return names.ToArray() End Function
调用示例:BuildNamesArray("CONST_FEN", 15) → 得到{"CONST_FEN1", "CONST_FEN2", ..., "CONST_FEN15"}
步骤2:反射获取常量值
编写函数通过常量名称获取对应值:
Function GetConstantValue(constantName As String, targetType As Type) As String ' 获取类的静态公共字段(常量编译后属于此类字段) Dim field = targetType.GetField(constantName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static) If field IsNot Nothing AndAlso field.IsLiteral Then ' IsLiteral标记字段为常量 Return CStr(field.GetValue(Nothing)) ' 静态字段无需实例,传入Nothing End If Throw New ArgumentException($"不存在名为 {constantName} 的常量") End Function
步骤3:构建字典
Dim fenDict As New Dictionary(Of String, String)() Dim constantNames = BuildNamesArray("CONST_FEN", 15) For Each name In constantNames fenDict.Add(name, GetConstantValue(name, Me.GetType())) ' Me.GetType()为常量所在类的类型 Next
注意:反射是运行时操作,存在轻微性能开销,但仅用于一次性字典构建时可忽略。
方案2:编译期代码生成(零运行时开销)
使用T4文本模板在编译阶段自动生成字典初始化代码,彻底避免手动维护,同时保证运行时性能最优。
创建FenConstants.tt模板文件,内容如下:
<#@ template language="VB" #> <#@ output extension=".vb" #> <# Const constantCount As Integer = 15 ' 常量总数 #> Public Module FenConstants ' 自动生成常量定义(如需单独使用常量) <# For i As Integer = 1 To constantCount #> Public Const CONST_FEN<#=i#> As String = "<#= GetFenValue(i) #>" <# Next #> ' 自动生成预初始化的字典 Public ReadOnly FenDictionary As New Dictionary(Of String, String) From { <# For i As Integer = 1 To constantCount #> {NameOf(CONST_FEN<#=i#>), CONST_FEN<#=i#>}<# If i < constantCount Then "," #> <# Next #> } ' 定义常量值的获取逻辑(可从配置文件/数据库读取,或硬编码) Private Function GetFenValue(index As Integer) As String Select Case index Case 1 Return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" Case 2 Return "r2qk2r/pp1n2p/2p1p2n1p/3p/3P/B1PB1N/P1P2PPP/N2Q2K w - - 0 1" ' ... 补充其他常量值 Case 15 Return "1r3r1k/6pp/6b/pBp3B/Pn1N2P/4p2P1P/2KR3R/ b - - 0 1" Case Else Return String.Empty End Select End Function End Module
编译项目时,模板会自动生成包含常量和字典的VB代码,直接使用FenConstants.FenDictionary即可。
方案3:直接构建字典(最简洁设计)
若无需单独定义常量,可跳过中间步骤,直接通过循环初始化字典:
Public ReadOnly FenDictionary As New Dictionary(Of String, String)() Sub New() For i As Integer = 1 To 15 Dim key = $"CONST_FEN{i}" FenDictionary.Add(key, GetFenValue(i)) Next End Sub Private Function GetFenValue(index As Integer) As String Select Case index Case 1 Return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" Case 2 Return "r2qk2r/pp1n2p/2p1p2n1p/3p/3P/B1PB1N/P1P2PPP/N2Q2K w - - 0 1" ' ... 补充其他常量值 Case 15 Return "1r3r1k/6pp/6b/pBp3B/Pn1N2P/4p2P1P/2KR3R/ b - - 0 1" Case Else Return String.Empty End Select End Function
这种方式直接完成字典构建,代码最简洁,无需额外处理常量与字符串的映射。
内容的提问来源于stack exchange,提问作者Reinhard Neuwirth
相关产品推荐
相关产品推荐

