XML-литералы в коде VB.NET не работают с операторами #if
У меня есть проект 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>
Недавно мне нужно было две сборки проекта, которые немного различаются (я не хочу платить за библиотечный код для многих пользователей). Итак, у меня есть одна сборка, в которой я выбрал все инструменты пользовательского интерфейса, связанные со штрих-кодом. Это прекрасно работает везде, кроме XML-литералов, подобных этому
#if USE_BAR_CODE=1
<node key="barcode" name="Barcode Entry" ctrl="EditMfgEntry" type="mfg"> </node>
#end if
Если я установлю USE_BAR_CODE в 0, я все равно получу литерал xml внутри блока #if, но везде в моем коде, где я использовал обычный источник VB, код не был скомпилирован.
Это наводит меня на мысль, что процесс компиляции обрабатывает литералы xml ДО операторов #if. Я что-то пропустил?
2 ответа
Может быть, это совсем не решение проблемы, но, как гласит пословица: "Плохой кустарник лучше открытого поля".
Основная идея заключается в использовании узла инструкции обработки. Если элемент имеет инструкцию обработки над ним, пропустите его, в противном случае включите его. Таким образом, вы можете контролировать "инклюзивность" этого элемента.
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))
К сожалению, нет, вы не можете использовать такие директивы в литералах. Под капотом поведение такое же как 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