VB.NET 代码中的 XML 文字似乎不适用于 #if 语句

问题描述 投票:0回答:3

我有一个 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>

我最近需要有两个略有不同的项目版本(不想为许多用户支付库代码费用)。所以我有一个构建,其中我 #if 出了所有与条形码相关的 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 文字。我错过了什么吗?

vb.net xml-literals
3个回答
1
投票

不幸的是,你不能在文字中使用这样的指令。在幕后,其行为与

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

0
投票

可能根本不是解决方案,但正如谚语所说“坏灌木胜过空地”。 😉

主要思想是利用处理指令节点。如果元素上面有处理指令,则跳过它,否则包含它。这样你就可以控制该元素的“包容性”。

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))

0
投票

寻找其他东西并遇到了这个。如果你可以添加另一个变量...

#Const USE_BAR_CODE = 1

    Dim xe As XElement '= XElement.Load("URI")

    Dim _USE_BAR_CODE As Boolean = False

#If USE_BAR_CODE = 1 Then
    _USE_BAR_CODE = True
#End If
    xe = <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>
                 <%= If(_USE_BAR_CODE, <node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"></node>, Nothing) %>
             </node>
         </nodes>
© www.soinside.com 2019 - 2024. All rights reserved.