<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Don's McBlog</title><link>http://blogs.msdn.com/don_mccrady/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Expression Editor Quirks (or CodeDom Quirks II)</title><link>http://blogs.msdn.com/don_mccrady/archive/2007/01/05/expression-editor-quirks-or-codedom-quirks-ii.aspx</link><pubDate>Fri, 05 Jan 2007 22:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1417587</guid><dc:creator>dmccrady</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/don_mccrady/comments/1417587.aspx</comments><wfw:commentRss>http://blogs.msdn.com/don_mccrady/commentrss.aspx?PostID=1417587</wfw:commentRss><description>&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;It's been a while since I've updated this.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;My apologies, but I do tend to disappear from work for the month of December, which is what I did this year too.&amp;nbsp; Happy 2007!&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;This article can be considered somewhat of a sequel to my last one (CodeDom Quirks), but now I'll focus on some quirkiness of the WF Rules expression editors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The same editor is used to author and edit both Declarative Rule Conditions (the Condition editor) as well as Rule conditions and actions (the RuleSet editor).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Both support a natural algebraic expression language that parses a large subset of what C# can express.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;As I mentioned in the previous article, the parser behind these designers consumes an expression and translates into an expression object model used by WF Rules, namely CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thus if you enter the following into the condition editor:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;2 + 3 == 5&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;the editor parses this and saves it as a CodeDom tree, just as if you had created the following CodeDom tree yourself:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(2),&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.Add,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(3)),&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.ValueEquality,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(5))&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;This CodeDom is then serialized out to the .rules file, where you can see that it shows up just as XML serialized CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic"&gt;Note that the original text (2+3==5) was never saved&lt;/SPAN&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you re-edit the expression (in fact, as soon as you press &amp;lt;TAB&amp;gt; in the dialog), the CodeDom is decompiled back into a canonical string form.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It turns out that this is the source of many of the "quirks" described in this article, because the decompile may not preserve the exact syntax you wrote.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;SPACING&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;At its most basic level, this decompilation process will strip out any excess spaces, or add spaces.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;2+&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;3&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;==5&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;will simply end up being decompiled as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;2 + 3 == 5&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;That's fairly innocuous, but there are a few instances where the canonical form may surprise you (and I admit, there are times when it may annoy you).&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;PARENTHESES&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;The decompilation uses the minimum amount of parenthesization necessary to preserve operator precedence.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thus if you enter the following into the condition editor:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;((2 - 3) + 4) == 3&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and hit &amp;lt;TAB&amp;gt;, your expression will be replaced by:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;2 - 3 + 4 == 3&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;All the parentheses disappear because they're all redundant.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;ZERO MINUS&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Remember in the last article when I said the unary negation operator was not supported by CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;No problem, the expression editor will still parse "-x" and turn it into "0 - x".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The decompilation is even smart enough to show "0 - x" as "-x".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Pretty smart, eh?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, if you enter the following into the condition editor:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;3 + (0 - 5) == (0 - 2)&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and hit &amp;lt;TAB&amp;gt;, your expression will be rewritten as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;3 + -5 == -2&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;The "pretty smart" decompilation really can't tell whether you typed "0 - 5" or whether you typed "-5" because they're both represented by the same CodeDom tree.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;I do like to think that the canonical form is simpler in this case.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;EQUAL FALSE&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Similarly, recall that CodeDom does not support a unary NOT operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The expression editor still parses "!x" and turns it into "x == false".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once again the decompilation is smart enough to show "x == false" as "!x".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But once again, if you entered:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;(2 &amp;gt; 5) == false&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and hit &amp;lt;TAB&amp;gt;, your expression will be rewritten as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;!(2 &amp;gt; 5)&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;This may or may not be more readable depending on your taste, but it is the canonical representation of the "== false" pattern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that if you'd entered:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;(2 == 5) == false&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;the decompilation would be even smarter and rewrite this as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;2 != 5&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;which is, in my opinion, a much simpler expression.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;ALTERNATE OPERATOR SPELLINGS&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;To make the condition editor's expression language more approachable to a wider audience of developers, we chose to support some alternate operator spellings.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most of these alternate spellings come from VB.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So instead of "!=" you can use "&amp;lt;&amp;gt;".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead of unary "!" you can use "NOT".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here's a complete list:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in; MARGIN-BOTTOM: 0in; MARGIN-LEFT: 0.75in; DIRECTION: ltr; unicode-bidi: embed" type=circle&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Inequality:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;!=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Unary NOT:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;!&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;NOT&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Boolean AND:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;&amp;amp;&amp;amp;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;AND&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Boolean OR:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;||&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;OR&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Modulus:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;%&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;MOD&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;This reference:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;this&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;me&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle"&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;Null reference:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;null&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri"&gt;nothing&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.75in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;However, only the operator spellings in &lt;SPAN style="FONT-WEIGHT: bold"&gt;bold&lt;/SPAN&gt; will be preserved by the decompilation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thus, if you type:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;me.x &amp;lt;&amp;gt; 5 AND me.y == nothing&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and hit &amp;lt;TAB&amp;gt;, the expression will get rewritten to:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;this.x != 5 &amp;amp;&amp;amp; this.y == null&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;This may definitely fall into the category of "annoying", but simply reflects our teams C# bias.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;My apologies to all esteemed VB'ers out there.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;QUALIFIED TYPE NAMES&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;The expression editor will allow you to refer to unqualified type names as long as they have unambiguous names.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if you have types "Foo.Glorp" and "Bar.Glorp", you cannot unambiguously refer to the type as "Glorp"; you have to use the fully qualified type name.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the other hand the type "Console" refers unambiguously to "System.Console", so you can refer to it just as "Console".&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;The decompilation does not know what type names are unique, so it always fully-qualifies them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thus if you type:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;DateTime.Now.Year == 2007&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and press &amp;lt;TAB&amp;gt;, this will get rewritten as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;System.DateTime.Now.Year == 2007&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;EXPLICIT "THIS" QUALIFICATION&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Like C#, the expression editor will allow you to refer to an instance member of the "ambient" class without qualifying it with "this.".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a workflow application, the ambient class is always the root workflow class.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If your workflow type has an instance field "int foo", you can enter the following expression in the editor:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;foo &amp;gt; 25&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;However, when you press &amp;lt;TAB&amp;gt;, the canonicalized representation will be decompiled as:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: 'Courier New'"&gt;this.foo &amp;gt; 25&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;We chose to be explicit about "this." qualification because unlike an instance method within a C# class, it is not obvious what the ambient class is.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Making "this." qualification explicit helps make developers aware of the context in which they are accessing data.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;SUMMARY&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;If you use the WF Rules expression editor enough, you may run into other CodeDom decompilation "quirks" that I have not mentioned.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;By all means let me know if you find anything else surprising and/or annoying.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1417587" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/don_mccrady/archive/tags/WF+Rules/default.aspx">WF Rules</category></item><item><title>CodeDom Quirks</title><link>http://blogs.msdn.com/don_mccrady/archive/2006/10/11/codedom-quirks.aspx</link><pubDate>Wed, 11 Oct 2006 20:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:817234</guid><dc:creator>dmccrady</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/don_mccrady/comments/817234.aspx</comments><wfw:commentRss>http://blogs.msdn.com/don_mccrady/commentrss.aspx?PostID=817234</wfw:commentRss><description>&amp;nbsp; 
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;I'm going to talk a little bit here about the expression model used by WF rules, and some of the idiosyncrasies, caveats, and downright quirks that arise from our chosen expression model. &lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;First, a little history.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rather than (re)inventing our own private Rule expression object model, the WF Rules team opted to leverage an existing expression model, namely CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;CodeDom was originally intended as an object model for code emitters: i.e., VS-based designers like WinForms, and the like.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The object model forms an abstraction that enables these designers to target C# and VB developers without having to bake language-specific notions into their tools.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;WF Rules takes CodeDom to the next level by enabling semantic validation and execution of CodeDom trees.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Using CodeDom, WF Rules supports a very large expression language subset that is very close to what C# and VB support.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you can model it in CodeDom (and sometimes even if you can't, as we'll see), you can execute it using WF Rules.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It's actually pretty heady stuff, and includes complex name resolution, type checking, and method overloading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In future releases we will consider operator overloading as well.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;CodeDom is a fairly rich object model for expressions, supporting a large subset of arithmetic and programmatic expressions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, it has some annoying gaps.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;Value Inequality&lt;/SPAN&gt;:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;CodeDom's CodeBinaryOperatorType enumeration supports "ValueEquality", but there's no "ValueInequality" operator.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That's like being able to write "x == y", but not "x != y".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This does seem quite limiting, especially in a Boolean-heavy environment like Rules.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately, there's a simple way to express inequality in terms of the supported "ValueEquality":&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;x != y&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;→&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(x == y) == false&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;In CodeDom, this would be constructed using something like:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; FONT-FAMILY: 'Times New Roman'"&gt;x&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.ValueEquality,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; FONT-FAMILY: 'Times New Roman'"&gt;y)&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.ValueEquality,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(false))&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;Left shift, right shift, and bitwise XOR&lt;/SPAN&gt;:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;While CodeDom supports bitwise AND and bitwise OR operations, there is no support for left or right shifting, and no support for the XOR operator.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don't lose much sleep over this, since these operators aren't often used, especially in high-level Rule Sets.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;Boolean NOT&lt;/SPAN&gt;:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The unary "not" operator cannot be modeled directly in CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Actually, CodeDom does not support any unary operators.)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once again, this seems kind of limiting for a Boolean-heavy feature such as Rules, but again there's a fairly simple workaround that is very similar to our "Value Inequality" transformation above:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;not&lt;/SPAN&gt; x&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;→&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;x == false&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;In CodeDom, this would be constructed using something like:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; FONT-FAMILY: 'Times New Roman'"&gt;x&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.ValueEquality,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(false))&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;As we can see, the Boolean "not" operation is just a variant of the "Value Inequality" case.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;Unary Negation&lt;/SPAN&gt;:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The unary negation operator cannot be directly modeled in CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Fortunately, negation can be expressed in terms of binary subtraction:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;-&lt;/SPAN&gt;x&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;→&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;0 - x&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;In CodeDom, this would be constructed using something like:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;new CodeBinaryOperatorExpression(&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;new CodePrimitiveExpression(0),&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CodeBinaryOperatorType.Subtract,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; FONT-FAMILY: 'Times New Roman'"&gt;x&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;Bitwise NOT&lt;/SPAN&gt;:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is another unary operator that cannot be modeled directly in CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In theory, this operation can be implemented using the substitution:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;&lt;SPAN style="FONT-WEIGHT: bold"&gt;~&lt;/SPAN&gt;x&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;→&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;x &lt;SPAN style="FONT-WEIGHT: bold"&gt;xor&lt;/SPAN&gt; 0xFFFFFFFF&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;(assuming "x" is an unsigned 32-bit integer).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, recall that CodeDom cannot model the XOR operator either.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So we're stuck in this case; CodeDom cannot represent bitwise NOT.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, like the shift operators, I believe bitwise NOT is a rarely used operator, which we can live without.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;WORKAROUNDS&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;In the end, if an operator is not explicitly supported by CodeDom, its result can almost always be achieved by calling a helper method.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;WF Rules also supports custom extensions to CodeDom, so you can add whatever missing operations you like and use them in your rule expressions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I'll try to cover this in more detail in a later article.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;DESIGN-TIME IMPLICATIONS&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;The Condition editor and the RuleSet editors have a text-based, parser-driven interface that allows WF Rules users to enter their expressions in a natural syntax, and not be too particularly concerned with the fact that it's doing nothing more than building CodeDom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, the parser behind it will happily consume the following expressions:&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;-x&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;!x&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri"&gt;x != y&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;and do the appropriate transformations into CodeDom for you automatically.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;In a future article, I'll talk about more design-time implications that arise from our use of an expression object model to represent Rules expressions.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=817234" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/don_mccrady/archive/tags/WF+Rules/default.aspx">WF Rules</category><category domain="http://blogs.msdn.com/don_mccrady/archive/tags/CodeDom/default.aspx">CodeDom</category></item><item><title>Rete?</title><link>http://blogs.msdn.com/don_mccrady/archive/2006/09/09/748368.aspx</link><pubDate>Sun, 10 Sep 2006 07:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:748368</guid><dc:creator>dmccrady</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/don_mccrady/comments/748368.aspx</comments><wfw:commentRss>http://blogs.msdn.com/don_mccrady/commentrss.aspx?PostID=748368</wfw:commentRss><description>&amp;nbsp;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;It seems that every thing that is to be called a Rules Engine must claim to implement the Rete Algorithm.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Microsoft's BRE does, Oracle's new Business Rules product does, iLog does, and the list goes on.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Going against the tide, the Rules Engine in Windows Workflow Foundation (WF Rules) does &lt;SPAN style="FONT-STYLE: italic"&gt;not&lt;/SPAN&gt; implement the Rete algorithm.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is not to say that it won't in the future, but in the near term, it won't.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;Why not?&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;Let me first give a simple practical reason.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;WF Rules was developed on a short development cycle, so we just didn't have time to implement it, let alone test it.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;There are plenty of resources out there that describe what the Rete algorithm does and why it is so often used in Rules engines.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At the end of the day, Rete is an &lt;SPAN style="FONT-STYLE: italic"&gt;optimization&lt;/SPAN&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You don't &lt;SPAN style="FONT-STYLE: italic"&gt;need&lt;/SPAN&gt; a Rete engine to implement a forward-chaining rules engine; however, the Rete optimization may improve the runtime performance of a Rule Set.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That's what optimizations do.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In particular, Rete reduces the number of predicate evaluations by remembering the most recent value and re-using it on subsequent re-evaluations.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;Ironically, I love optimization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I have a compiler-development background, and local &amp;amp; global compiler optimization techniques are fascinating subjects, and fun projects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Implementing the Rete optimization for WF Rules would have been a cool way to spend a coding milestone.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;However, I also know that before you try applying a lot of cool optimizations to a project, you should try to make sure that they solve real bottlenecks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Turning on the C++ compiler's global optimizer will do a lot of cool optimizing transformations to your program; but if your program's performance is dominated by network I/O, it won't make a bit of difference.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;The same logic applies to Rules solutions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Sometimes (quite often, I'd actually argue), a Rule Set is structured in such a way that there are no opportunities for the Rete optimization to make any difference.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if each rule evaluates totally independent expressions against different facts, the Rete algorithm will yield no improvement.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, its intrinsic overhead may result in a net &lt;SPAN style="FONT-STYLE: italic"&gt;loss&lt;/SPAN&gt; of performance.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;I certainly concede that there are many examples of Rule Sets that contain a lot of common predicates.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In those cases, a Rete-based Rules engine like BRE will &lt;SPAN style="FONT-STYLE: italic"&gt;crush&lt;/SPAN&gt; a non-Rete engine like WF Rules.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;However, in cases where there are few common predicates, the reverse has also been demonstrated:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;WF Rules and its non-Rete execution mechanism will &lt;SPAN style="FONT-STYLE: italic"&gt;crush&lt;/SPAN&gt; Rete-based BRE.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;My point is simply that Rete is an optimization strategy that is not necessarily appropriate for all Rules-based solutions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For WF Rules, we placed much more importance on how much you can express in your Rules, how easy it is to express it, and how well it integrates into Windows Workflow Foundation and the .NET framework.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;Performance optimizations for WF Rules are certainly coming in the future.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But even without Rete, WF Rules is already a highly performant Rules engine.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=748368" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/don_mccrady/archive/tags/WF+Rules/default.aspx">WF Rules</category></item><item><title>Intro</title><link>http://blogs.msdn.com/don_mccrady/archive/2006/09/09/intro.aspx</link><pubDate>Sun, 10 Sep 2006 06:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:748353</guid><dc:creator>dmccrady</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/don_mccrady/comments/748353.aspx</comments><wfw:commentRss>http://blogs.msdn.com/don_mccrady/commentrss.aspx?PostID=748353</wfw:commentRss><description>&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;I suppose the first entry in blog should be an introduction of sorts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since this is a Microsoft blog, I'll mention immediately that&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I do work at Microsoft, and have since 1997.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Prior to that I worked at IBM for 8 years.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I am currently the development lead for the Windows Workflow Foundation Rules team.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The content of this blog will therefore focus mostly on the WF Rules technology that I helped develop, and that I currently lead.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;I should point out that I'm not a big fan of blogs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Heck, I don't even like the word "blog", which frankly sounds more like a bodily function than anything else ("... he got so drunk, he blogged all over the place").&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, they're undeniably popular and occasionally useful sources of information, and I believe I can add my tiny bit of wisdom to those who happen to land on this site via a link or a search.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri; mso-outline-level: 1"&gt;Finally, for a glimpse at my other life, you can check out my stargazing &amp;amp; astrophotography web site at &lt;A href="http://starryvistas.net/" mce_href="http://dandkmccrady.home.comcast.net/"&gt;http://starryvistas.net&lt;/A&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thanks.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=748353" width="1" height="1"&gt;</description></item></channel></rss>