我有一个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是常规VB源代码的地方,代码都没有编译。
这使我相信#if语句之前,编译过程会处理xml文字。我想念什么吗?
答案 0 :(得分: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
答案 1 :(得分: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))