BAM 侦听器配置文件使用筛选器表达式来标识活动,并使用数据表达式构造用于存储的数据元素、用作关联 ID 或延续标记或类似用途。 无论用途如何,各个表达式都由 expression 元素在侦听器配置文件中标识,并包含使用反向波兰表示法(也称为后缀表示法)的一个或多个操作。
关于逆波兰表示法
在逆波兰表示法 (RPN) 中,操作数的优先级高于运算符,因而不必使用括号作为优先运算符。 堆栈用于保存值,而所有运算或者将值推送到堆栈上,或者从堆栈中弹出(删除)值,或者执行推送和弹出的组合以完成某个运算。
例如,如果要计算表达式
5 + (10 - 2)
将该表达式转换为等效的 RPN 结果,形式如下
5 10 2 - +
该表达式计算过程如下:
| 输入 | 操作 | 堆栈 |
|---|---|---|
| 5 | 推送 | 5 |
| 10 | 推送 | 5、10 |
| 2 | 推送 | 5, 10, 2 |
| - | Subtract | 5, 8 |
| + | 添加 | 13 |
假设 RPN 系统支持字符串连接运算,也可以计算下列表达式
"The quick brown " + "fox " + "jumped over the lazy " + "dog."
将该表达式转换为等效的 RPN 符号可生成:
"The quick brown " "fox " "jumped over the lazy " "dog" + + +
该表达式计算过程如下:
| 输入 | 操作 | 堆栈 |
|---|---|---|
| “快速棕色” | 推送 | "The quick brown " |
| "fox" | 推送 | "The quick brown ", "fox " |
| "jumped over the lazy" | 推送 | "The quick brown ", "fox ", "jumped over the lazy " |
| "dog." | 推送 | "The quick brown ", "fox ", "jumped over the lazy ", "dog." |
| + | Concatenate | "The quick brown ", "fox ", "jumped over the lazy dog." |
| + | Concatenate | "The quick brown ", "fox jumped over the lazy dog." |
| + | Concatenate | "The quick brown fox jumped over the lazy dog." |
正如您所见,可以支持任意数量的运算,包括比较、布尔运算和用于检索适合于所参与运算的值的自定义运算。 各值将在此堆栈中进行累计并根据各个运算被推送到堆栈和弹出堆栈。
侦听器配置文件中的逆波兰表示法
将在侦听器配置文件中编写两种类型的表达式:筛选器表达式和数据表达式。 筛选器表达式预期 RPN 表达式的结果为布尔值 true ,而 false 数据表达式预期堆栈上的单个值。
筛选表达式
筛选器表达式的计算结果为 Boolean true 或 false ,用于标识在 WF 或 WFC 应用程序中跟踪的特定事件。 在 WF 应用程序中,通常根据活动名称和事件进行筛选。 例如,你可能希望在“关闭”时选择 FoodAndDrinksPolicy 活动。 使用 WF 运算,则可将此筛选器表示为:
(GetActivityName = "FoodAndDrinksPolicy") && (GetActivityEvent = "Closed")
将此表达式转换为 RPN 可生成:
GetActivityName "FoodAndDrinksPolicy" == GetActivityEvent "Closed" == &&
将此表达式转换为侦听器配置文件的等效表达式将生成以下 XML:
<ic:Filter>
<ic:Expression>
<wf:Operation Name="GetActivityName"/>
<ic:Operation Name="Constant">
<ic:Argument>FoodAndDrinksPolicy</ic:Argument>
</ic:Operation>
<ic:Operation Name="Equals"/>
<wf:Operation Name="GetActivityEvent"/>
<ic:Operation Name="Constant">
<ic:Argument>Closed</ic:Argument>
</ic:Operation>
<ic:Operation Name="Equals"/>
<ic:Operation Name="And"/>
</ic:Expression>
</ic:Filter>
最后,假设 GetActivityName 返回“DessertPolicy”且 GetActivityEvent 返回“Closed”,将按如下所示计算此表达式:
| 输入 | 操作 | 堆栈 |
|---|---|---|
| GetActivityName | "DessertPolicy" | |
| "FoodAndDrinksPolicy" | 一直 | "DessertPolicy", "FoodAndDrinksPolicy" |
| 等于 | 比较 | False |
| GetActivityEvent | False, Closed | |
| "Closed" | 一直 | False, "Closed", "Closed" |
| 等于 | 比较 | False、True |
| 且 | 逻辑与 | False |
堆栈上剩余的值是布尔值 False。 这将导致不会激发相应事件。 如果活动名称为“FoodAndDrinksPolicy”,则其计算结果为布尔值 True。
可以使用 WCF 操作 GetEndpointName 和 GetOperationName构造具有类似计算) 的类似表达式 (。
数据表达式
数据表达式用于定义单个字符串数据值。 数据表达式是未由 Filter 元素括起来的任何表达式。 数据表达式由OnEvent元素 CorrelationID、、 ContinuationTokenReference和 Update使用。
通常要求使用已标记的时间戳来更新 BAM 活动数据库。 例如,你可能希望使用格式为“Start: <EventTime>”的字符串来捕获事件开始的时间。 为此,需要使用类似以下格式的表达式(其中 + 表示连接):
"Start: " + GetContextProperty(EventTime)
将此表达式转换为 RPN 可生成:
"Start: " GetContextProperty(EventTime) +
将此表达式转换为侦听器配置文件中元素的等效表达式 Update 会导致以下 XML:
<ic:Update DataItemName="NewOrderCreateTime" Type="NVARCHAR">
<ic:Expression>
<ic:Operation Name="Constant">
<ic:Argument>Start:</ic:Argument>
</ic:Operation>
<wf:Operation Name="GetContextProperty">
<wf:Argument>EventTime</wf:Argument>
</wf:Operation>
<ic:Operation Name="Concatenate" />
</ic:Expression>
</ic:Update>
下表显示了在事件时间为“12:00 PM”的情况下如何解释该表达式。
| 输入 | 操作 | 堆栈 |
|---|---|---|
| “Start: ” | 一直 | “Start: ” |
| GetContextProperty(EventTime) | 推送 | “Start: ”, “2006-09-27T12:00:34.000Z” |
| Concatenate | Concatenate | “Start: 2006-09-27T12:00:34.000Z” |
update 命令使用的值为“Start: 2006-09-27T12:00:34.000Z”。
注意
不要在数据表达式中使用比较运算符“And”或“Equals”。 如果使用这两种运算符,则部署侦听器配置文件时将收到一个错误。