XML VB.NET 代码中的文字似乎不适用于 #if 语句
XML Literals in VB.NET Code don't seem work with #if statements
我有一个 vb.net 项目,它使用 XML 文字来配置用户界面导航栏。代码看起来像这样并且已经工作了很多年。
Private ReadOnly _actionTreeXml As XElement =
<nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
我最近需要有两个略有不同的项目 uilds(不想为许多用户支付库代码)。所以我有一个 build,其中我 #if out 所有与条形码相关的 ui 工具。这在任何地方都很好用,除了 XML 这样的文字
#if USE_BAR_CODE=1
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"> </node>
#end if
如果我将 USE_BAR_CODE 设置为 0,我仍然会在 #if 块中得到 xml 文字,但在我的代码中,我经常使用 #if'ed 的所有地方 VB 来源代码未编译。
这让我相信编译过程会在 #if 语句之前处理 xml 文字。我错过了什么吗?
很遗憾,您不能在文字中使用这样的指令。在幕后,行为与 If, Then and Else
语句相同。你不能像现在这样直接把它们放在一起,你必须包装代码块来告诉编译器要编译什么而不是像标准 If, Then and Else
语句那样编译 运行 时间。条件编译块中的语句必须是完整的逻辑语句。例如,您不能有条件地只编译文字、函数等的属性...
下面是一个快速解决方案,可以包含或不包含节点。这也经过测试并且工作正常。
#If USE_BAR_CODE = 1 Then
Private ReadOnly _actionTreeXml As XElement = <nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
#Else
Private ReadOnly _actionTreeXml As XElement = <nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
#End If
可能根本不是解决方案,但正如谚语所说 "A bad bush is better than the open field"。
主要思想是使用处理指令节点。如果元素上面有处理指令,则跳过它,否则包含它。这样你就可以控制那个元素的"inclusiveness"。
1)首先创建扩展方法:
Module XmlExtentions
<System.Runtime.CompilerServices.Extension>
Function Filter(root_node As IEnumerable(Of XElement)) As IEnumerable(Of XElement)
Return root_node.First().Elements().Where(
Function(e)
If e.PreviousNode Is Nothing Then Return True
Return e.PreviousNode.NodeType <> Xml.XmlNodeType.ProcessingInstruction
End Function)
End Function
End Module
2。查询我们的XML:
Dim _actionTreeXml As XElement =
<nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<?Skip-Element?>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
Dim elements = _actionTreeXml.<node>.Filter()
'// Do something...
elements.ToList().ForEach(Sub(e) Console.WriteLine(e))
我有一个 vb.net 项目,它使用 XML 文字来配置用户界面导航栏。代码看起来像这样并且已经工作了很多年。
Private ReadOnly _actionTreeXml As XElement =
<nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
我最近需要有两个略有不同的项目 uilds(不想为许多用户支付库代码)。所以我有一个 build,其中我 #if out 所有与条形码相关的 ui 工具。这在任何地方都很好用,除了 XML 这样的文字
#if USE_BAR_CODE=1
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"> </node>
#end if
如果我将 USE_BAR_CODE 设置为 0,我仍然会在 #if 块中得到 xml 文字,但在我的代码中,我经常使用 #if'ed 的所有地方 VB 来源代码未编译。
这让我相信编译过程会在 #if 语句之前处理 xml 文字。我错过了什么吗?
很遗憾,您不能在文字中使用这样的指令。在幕后,行为与 If, Then and Else
语句相同。你不能像现在这样直接把它们放在一起,你必须包装代码块来告诉编译器要编译什么而不是像标准 If, Then and Else
语句那样编译 运行 时间。条件编译块中的语句必须是完整的逻辑语句。例如,您不能有条件地只编译文字、函数等的属性...
下面是一个快速解决方案,可以包含或不包含节点。这也经过测试并且工作正常。
#If USE_BAR_CODE = 1 Then
Private ReadOnly _actionTreeXml As XElement = <nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
#Else
Private ReadOnly _actionTreeXml As XElement = <nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
#End If
可能根本不是解决方案,但正如谚语所说 "A bad bush is better than the open field"。
主要思想是使用处理指令节点。如果元素上面有处理指令,则跳过它,否则包含它。这样你就可以控制那个元素的"inclusiveness"。
1)首先创建扩展方法:
Module XmlExtentions
<System.Runtime.CompilerServices.Extension>
Function Filter(root_node As IEnumerable(Of XElement)) As IEnumerable(Of XElement)
Return root_node.First().Elements().Where(
Function(e)
If e.PreviousNode Is Nothing Then Return True
Return e.PreviousNode.NodeType <> Xml.XmlNodeType.ProcessingInstruction
End Function)
End Function
End Module
2。查询我们的XML:
Dim _actionTreeXml As XElement =
<nodes>
<node key="any" name="Top">
<node key="log" name="***LOGIN***" type="everybody"></node>
<node key="op" name="Home" ctrl="uiHomePage" type="mfg"></node>
<?Skip-Element?>
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>
<node key="wip" name="Work in Progress" ctrl="QueryWIP" type="mfg"></node>
<node key="readme" name="Version Info" type="everybody"></node>
</node>
</nodes>
Dim elements = _actionTreeXml.<node>.Filter()
'// Do something...
elements.ToList().ForEach(Sub(e) Console.WriteLine(e))