<?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>Matt W's Windows Workflow Place : activities</title><link>http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx</link><description>Tags: activities</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Finding the Variables in Scope Within the WF Designer</title><link>http://blogs.msdn.com/mwinkle/archive/2009/11/06/finding-the-variables-in-scope-within-the-wf-designer.aspx</link><pubDate>Fri, 06 Nov 2009 06:21:35 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9918399</guid><dc:creator>mwinkle</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/9918399.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=9918399</wfw:commentRss><description>&lt;p&gt;In this &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/53c91c81-02cf-4eab-b43f-c3d73a03c501"&gt;thread&lt;/a&gt;, one of our forum customers asked the question:&lt;/p&gt;  &lt;h2&gt;“how do I find all of the variables that are in scope for a given activity in the designer?”&lt;/h2&gt;  &lt;p&gt;We do not have a public API to do this.&amp;#160; Internally we have a helper type called VariableHelper that we use to display the list of variables in the variable designer, as well as passed into the expression text box intellisense control. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_thumb.png" width="603" height="280" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_thumb_1.png" width="319" height="235" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;One thing that I would like to point out is that if you are implementing your expression editor and want to be able to enumerate the variables (to highlight the tokens that are in scope), your implementation of &lt;a href="http://msdn.microsoft.com/en-us/library/system.activities.presentation.view.iexpressioneditorservice.createexpressioneditor(VS.100).aspx"&gt;IExpressionEditorService.CreateExpressionEditor&lt;/a&gt;() will get a list of model items that correspond to the inscope variables.&amp;#160; &lt;/p&gt;  &lt;p&gt;Now, if you are not building an expression editor, and want to be able to enumerate all of the in scope variables, you will need to do a little more work.&amp;#160; Here are the basic steps&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Go to parent container&lt;/li&gt;    &lt;li&gt;Does it contain variables*&lt;/li&gt;    &lt;li&gt;Does it have a parent?&lt;/li&gt;    &lt;li&gt;Go to parent’s parent&lt;/li&gt;    &lt;li&gt;Repeat from step 2&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;* This is basically the tricky part, because it is not something we can cleanly determine (and it can also be altered at runtime by adding some additional ones via the CacheMetadata() method.&amp;#160; I’ll describe what the designer is currently doing to accumulate this list, and then talk about designs we could have in a future release. &lt;/p&gt;  &lt;h2&gt;Current Approach&lt;/h2&gt;  &lt;p&gt;Currently, there are two things that we look for when we navigate up the model item tree.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Collections of Variables name Variables&lt;/li&gt;    &lt;li&gt;Variables injected by the use of ActivityAction&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;As we walk up the tree, we need to find these.&amp;#160; Let’s first consider the following workflow we will use for our tests:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;wd.Load(&lt;span class="kwrd"&gt;new&lt;/span&gt; Sequence&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    Activities =&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="kwrd"&gt;new&lt;/span&gt; Sequence&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            Activities = &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                &lt;span class="kwrd"&gt;new&lt;/span&gt; ForEach&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                    Body = &lt;span class="kwrd"&gt;new&lt;/span&gt; ActivityAction&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                         Argument = &lt;span class="kwrd"&gt;new&lt;/span&gt; DelegateInArgument&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; { Name=&lt;span class="str"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; },&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                         Handler = &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                            &lt;span class="kwrd"&gt;new&lt;/span&gt; Sequence&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                            {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                                Activities = &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                                {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                                    &lt;span class="kwrd"&gt;new&lt;/span&gt; WriteLine()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;                                }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;});&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Line 13 is the only one that might look a little different here, I’ll eventually have a post up about &lt;a href="http://msdn.microsoft.com/en-us/library/dd485397(VS.100).aspx"&gt;ActivityAction&lt;/a&gt; that talks in more detail what’s going on there.&lt;/p&gt;

&lt;p&gt;So, this loaded in a rehosted designer looks like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_thumb_2.png" width="234" height="373" /&gt;&lt;/a&gt;&amp;#160;&amp;#160; &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s look at the code to figure out what is in scope of the selected element.&amp;#160; First, let’s get the selected element :-) &lt;/p&gt;

&lt;pre class="csharpcode"&gt; Selection  sel = wd.Context.Items.GetValue&amp;lt;Selection&amp;gt;();
 &lt;span class="kwrd"&gt;if&lt;/span&gt; (sel != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
 {
        ModelItem mi = sel.PrimarySelection;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;mi is now the model item of my selected item.&amp;#160; Let’s write some code to walk up the tree and add to a collection called variables&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;while&lt;/span&gt; (mi.Parent != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    Type parentType = mi.Parent.ItemType;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Activity).IsAssignableFrom(parentType))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="rem"&gt;// we have encountered an activity derived type&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="rem"&gt;// look for variable collection&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        ModelProperty mp = mi.Parent.Properties[&lt;span class="str"&gt;&amp;quot;Variables&amp;quot;&lt;/span&gt;];&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != mp &amp;amp;&amp;amp; mp.PropertyType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Collection&amp;lt;Variable&amp;gt;))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            mp.Collection.ToList().ForEach(item =&amp;gt; variables.Add(item));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="rem"&gt;// now we need to look action handlers &lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="rem"&gt;// this will ideally return a bunch of DelegateArguments&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    var dels = mi.Properties.Where(p =&amp;gt; &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ActivityDelegate).IsAssignableFrom(p.PropertyType));&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var actdel &lt;span class="kwrd"&gt;in&lt;/span&gt; dels)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (actdel.Value != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var innerProp &lt;span class="kwrd"&gt;in&lt;/span&gt; actdel.Value.Properties)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(DelegateArgument).IsAssignableFrom(innerProp.PropertyType) &amp;amp;&amp;amp; &lt;span class="kwrd"&gt;null&lt;/span&gt; != innerProp.Value)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                    variables.Add(innerProp.Value);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;    mi = mi.Parent;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Lines 4-13 handle the case where I just encounter an activity.&amp;#160; Lines 16-29 handle the slightly more tricky case where I need to handle ActivityAction (which ultimately derives from ActivityDelegate).&amp;#160; There are a few loops there but basically I look through all of the properties of the item which inherit from ActivityDelegate.&amp;#160; For each one of those, and for each property on that, I look for properties assignable from &lt;a href="http://msdn.microsoft.com/en-us/library/system.activities.delegateargument(VS.100).aspx"&gt;DelegateArgument&lt;/a&gt;.&amp;#160; As I find them I add them to my collection of model items for variables.&amp;#160; &lt;/p&gt;

&lt;p&gt;In my WPF app, I have a simple list box that shows all of these.&amp;#160; Because of the loosely typed data template I use in my WPF app, I get a pretty decent display since they share common things like &lt;a href="http://msdn.microsoft.com/en-us/library/system.activities.presentation.model.modelitem.itemtype(VS.100).aspx"&gt;ItemType&lt;/a&gt; from ModelItem, and a &lt;a href="http://msdn.microsoft.com/en-us/library/system.activities.presentation.model.modelitem.name(VS.100).aspx"&gt;Name&lt;/a&gt; that routes through to the underlying Name property both elements share. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_8.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/FindingtheVariablesinScopeWithintheWFDes_13A44/image_thumb_3.png" width="438" height="116" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ListBox&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;listBox1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;Row&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;ColumnSpan&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;Column&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;DataTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt; &lt;span class="attr"&gt;Orientation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Horizontal&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Foo:&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt; &lt;span class="attr"&gt;FontWeight&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Bold&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;{Binding Path=ItemType}&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;{Binding Path=Name}&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;DataTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ListBox&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Potential Future Approach&lt;/h2&gt;

&lt;p&gt;Our approach outlined above is generally correct.&amp;#160; That said, you can imagine a deeply nested data structure on an activity that contain variables that get injected into the scope at runtime.&amp;#160; We need a way for an activity to provide a way to declare how to get all of its variables.&amp;#160; The current approach is one of inspection, which works for all of our activities. In the future we may need to add an extensibility point to allow an activity author to specify how to find the variables that are available to its children.&amp;#160; The way that we could do that is to introduce an “VariableResolver” attribute which points to a type (or maybe a Func&amp;lt;&amp;gt;) that operates on the activity and returns the list of variables.&amp;#160; Actually today you could likely introduce a custom type descriptor that lifted the variables out of the activity and surfaces them in such a way that they would be discovered by the inspection above.&amp;#160; &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Disclaimer: the Potential Future Approach is simply something that we’ve discussed that we could do, it does not represent something that we will do.&amp;#160; If you think that is an interesting extensibility point that you might want to take advantage of down the road, let me know.&amp;#160; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918399" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf4/default.aspx">wf4</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/beta/default.aspx">beta</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/vs2010/default.aspx">vs2010</category></item><item><title>Activities Survey</title><link>http://blogs.msdn.com/mwinkle/archive/2007/10/18/activities-survey.aspx</link><pubDate>Fri, 19 Oct 2007 00:29:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5513801</guid><dc:creator>mwinkle</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/5513801.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=5513801</wfw:commentRss><description>&lt;p&gt;So, we're getting close to .NET 3.5 getting out the door, and as always we're thinking about what comes next.&amp;#xA0; The activities team is looking how to make activities better going forward, and they are very interested in what you have to say, how you have been using them and how you'd like to use them.&lt;/p&gt;  &lt;p&gt;This feedback will help us understand how to shape the future of things and how we should think about the pain points you are experiencing.&lt;/p&gt;  &lt;p&gt;&lt;a href="https://live.datstat.com/MSCSD-Collector/Survey.ashx?Name=WF_Activities_Survey_blog"&gt;Fill survey out here!&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5513801" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf/default.aspx">wf</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/vNext/default.aspx">vNext</category></item><item><title>Implementing the N of M Pattern in WF</title><link>http://blogs.msdn.com/mwinkle/archive/2007/06/27/implementing-the-n-of-m-pattern-in-wf.aspx</link><pubDate>Wed, 27 Jun 2007 03:38:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3556624</guid><dc:creator>mwinkle</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/3556624.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=3556624</wfw:commentRss><description>&lt;p&gt;The second in my series of alternate execution patterns (&lt;a href="http://blogs.msdn.com/mwinkle/archive/2007/05/24/different-execution-patterns-with-wf-or-going-beyond-sequential-and-state-machine.aspx"&gt;part 1&lt;/a&gt;)  &lt;p&gt;I recently worked with a customer who was implementing what I would call a "basic" human workflow system. It tracked approvals, rejections and managed things as they moved through a customizable process. It's easy to build workflows like this with an Approval activity, but they wanted to implement a pattern that's not directly supported out of the box. This pattern, which I have taken to calling "n of m", is also referred to as a "&lt;a href="http://www.workflowpatterns.com/patterns/control/new/wcp35.php"&gt;Canceling partial join for multiple instances&lt;/a&gt;" in the van der Aalst taxonomy. &lt;p&gt;The basic description of this pattern is that we start m concurrent actions, and when some subset of those, n, complete, we can move on in our process and cancel the other concurrent actions. A common scenario for this is where I want to send a document for approval to 5 people, and when 3 of them have approved it, I can move on. This comes up frequently in human or task-based workflows. There are a couple of "business" questions which have to be answered as well, the implementation can support any set of answers for this: &lt;ul&gt; &lt;li&gt;What happens if an individual rejects? Does this stop the whole group from completing, or is it simply noted as a "no" vote? &lt;li&gt;How should delegation be handled? Some business want this to break out from the approval process at this point.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The first approach the customer took was to use the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.activities.conditionedactivitygroup.aspx"&gt;ConditionedActivityGroup&lt;/a&gt; (CAG). The CAG is probably one of the most sophisticated out of the box activities that we ship in WF today, and it does give you a lot of control. It also gives you the ability to set the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.activities.conditionedactivitygroup.untilcondition.aspx"&gt;Until&lt;/a&gt; condition which would allow us to specify the condition that the CAG could complete, and the others would be cancelled (see &lt;a href="http://msdn2.microsoft.com/en-us/library/ms741710.aspx"&gt;Using ConditionedActivityGroup&lt;/a&gt;) &lt;p&gt;&lt;img height="268" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/ImplementingtheNofMPatterninWF_F7F8/clip_image001_1.png" width="246" align="right"&gt; &lt;p&gt;ConditionedActivityGroup &lt;p&gt;What are pros and cons of this approach: &lt;p&gt;Pros &lt;ul&gt; &lt;li&gt;Out of the box activity, take it and go &lt;li&gt;Focus on approval activity &lt;li&gt;Possibly execute same branch multiple times&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Cons &lt;ul&gt; &lt;li&gt;Rules get complex ( what happens if the individual rejections causes everything to stop) &lt;li&gt;I need to repeat the same activity multiple times (especially in this case, it's an approval, we know what activity needs to be in the loop) &lt;li&gt;I can't control what else a developer may put in the CAG &lt;li&gt;We may want to execute on some set of approvers that we don't know at design time, imagine an application where one of the steps is defining the list of approvers for the next step. The CAG would make that kind of thing tricky.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This led us to the decision to create a composite activity that would model this pattern of execution. Here are the steps we went through: &lt;h3&gt;Build the Approval activity&lt;/h3&gt; &lt;p&gt;The first thing we needed was the approval activity. Since we know this is going to eventually have some complex logic, we decided to take the basic approach of inheriting from SequenceActivity and composing our approval activity out of other activities (sending email, waiting on notification, handling timeouts, etc.). We quickly mocked up this activity to have an "Approver" property, a property for a timeout (which will go away in the real version, but is useful to put some delays into the process. We also added some code activities which Console.WriteLine 'd some information out so we knew which one was executing. We can come back to this later and make it arbitrarily complex. We also added the cancel handler so that we can catch when this activity is canceled (and send out a disregard email, clean up the task list ,etc). Implementing ICompensatableActivity may also be a good idea so that we can play around with compensation if we want to (note, that we will only compensate the closed activities, not the ones marked as canceled). &lt;p&gt;&lt;img height="265" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/ImplementingtheNofMPatterninWF_F7F8/clip_image002.png" width="452"&gt; &lt;p&gt;Properties of the Approval Activity &lt;p&gt;&lt;img height="321" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/ImplementingtheNofMPatterninWF_F7F8/clip_image003.png" width="222"&gt; &lt;p&gt;Placing the Approval Activity inside our NofM activity. &lt;h3&gt;What does the execution pattern look like?&lt;/h3&gt; &lt;p&gt;Now that we have our approval activity, we need to determine how this new activity is going to execute. This will be the guide that we use to implement the execution behavior. There are a couple of steps this will follow &lt;ol&gt; &lt;li&gt;Schedule the approval's to occur in parallel, one per each approver submitted as one of the properties &lt;li&gt;Wait for each of those to finish. &lt;li&gt;When one finishes, check to see if the condition to move onward is satisfied (in this case, we increment a counter towards a "number of approvers required" variable. &lt;li&gt;If we have not met the criteria, we keep on going. [we'll come back to this, as we'll need to figure out what to do if this is the last one and we still haven't met all of the criteria.] &lt;li&gt;If we have met the criteria, we need to cancel the other running activities (they don't need to make a decision any more).&lt;/li&gt; &lt;li&gt;Implement the easy part of this (scheduling the approvals to occur in parallel)&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;I say this is the easy part as this is documented in a number of places, including&lt;a href="http://www.amazon.com/Essential-Workflow-Foundation-Microsoft-Development/dp/0321399838/ref=pd_bbs_sr_1/105-8140718-5930861?ie=UTF8&amp;amp;s=books&amp;amp;qid=1179959181&amp;amp;sr=8-1"&gt; Bob and Dharma's book&lt;/a&gt;. The only trickery occurring here is that we need to clone the template activity, that is the approval activity that we placed inside this activity before we started working on it. This is a topic discussed in Nate's now &lt;a href="http://blogs.msdn.com/advancedworkflow/archive/2006/03/21/557121.aspx"&gt;defunct blog&lt;/a&gt;.&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {
        &lt;span class="rem"&gt;// here's what we need to do.&lt;/span&gt;
        &lt;span class="rem"&gt;// 1.&amp;gt; Schedule these for execution, subscribe to when they are complete&lt;/span&gt;
        &lt;span class="rem"&gt;// 2.&amp;gt; When one completes, check if rejection, if so, barf&lt;/span&gt;
        &lt;span class="rem"&gt;// 3.&amp;gt; If approve, increment the approval counter and compare to above&lt;/span&gt;
        &lt;span class="rem"&gt;// 4.&amp;gt; If reroute, cancel the currently executing branches.&lt;/span&gt;
        ActivityExecutionContextManager aecm = executionContext.ExecutionContextManager;
        &lt;span class="kwrd"&gt;int&lt;/span&gt; i = 1;
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; approver &lt;span class="kwrd"&gt;in&lt;/span&gt; Approvers)
        {
            &lt;span class="rem"&gt;// this will start each one up.&lt;/span&gt;
            ActivityExecutionContext newContext = aecm.CreateExecutionContext(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities[0]);
            GetApproval ga = newContext.Activity &lt;span class="kwrd"&gt;as&lt;/span&gt; GetApproval;
            ga.AssignedTo = approver;
            &lt;span class="rem"&gt;// this is just here so we can get some delay and "long running ness" to the&lt;/span&gt;
            &lt;span class="rem"&gt;// demo&lt;/span&gt;
            ga.MyProperty = &lt;span class="kwrd"&gt;new&lt;/span&gt; TimeSpan(0, 0, 3 * i);
            i++;
            &lt;span class="rem"&gt;// I'm interested in what happens when this guy closes.&lt;/span&gt;
            newContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, &lt;span class="kwrd"&gt;this&lt;/span&gt;);
            newContext.ExecuteActivity(newContext.Activity);
        }
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ActivityExecutionStatus.Executing;
    }
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Code in the execute method
&lt;p&gt;One thing that we're doing here is &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.activity.registerforstatuschange.aspx"&gt;RegisterForStatusChange()&lt;/a&gt; This is a friendly little method that will allow me to register for a status change event (thus it is very well named). This is a property of Activity, and I can register for different activity events, like &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.activity.closedevent.aspx"&gt;Activity.ClosedEvent&lt;/a&gt; or &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.activity.cancelingevent.aspx"&gt;Activity.CancelingEvent&lt;/a&gt;. On my NofM activity, I implment &lt;a href="http://msdn2.microsoft.com/en-us/library/aa480200.aspx"&gt;IActivityEventListener&lt;/a&gt; of type &lt;a href="http://msdn2.microsoft.com/en-us/library/aa480200.aspx"&gt;ActivityExecutionStatusChangedEvent&lt;/a&gt; (check out &lt;a href="http://msdn2.microsoft.com/en-us/library/aa480200.aspx"&gt;this article&lt;/a&gt; as to what that does and why). This causes me to implement OnEvent which since it comes from a generic interface is now strongly typed to accept the right type of event arguments in. That's always a neat trick that causes me to be thankful for generics. That's going to lead us to the next part.
&lt;h3&gt;Implement what happens when one of the activities complete&lt;/h3&gt;
&lt;p&gt;Now we're getting to the fun part of how we handle what happens when one of these approval activities return. For the sake of keeping this somewhat brief, I'm going to work off the assumption that a rejection does not adversely affect the outcome, it is simply one less person who will vote for approval. We can certainly get more sophisticated, but that is not the point of this post! ActivityExecutionStatusChangedEventArgs has a very nice Activity property which will return the Activity which is the one that caused the event. This let's us find out what happened, what the decision was, who it was assigned to, etc. I'm going to start by putting the code for my method in here and then we'll walk through the different pieces and parts.&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnEvent(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, ActivityExecutionStatusChangedEventArgs e)
{
    ActivityExecutionContext context = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; ActivityExecutionContext;
    &lt;span class="rem"&gt;// I don't need to listen any more&lt;/span&gt;
    e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, &lt;span class="kwrd"&gt;this&lt;/span&gt;);
    numProcessed++;
    GetApproval ga = e.Activity &lt;span class="kwrd"&gt;as&lt;/span&gt; GetApproval;
    Console.WriteLine(&lt;span class="str"&gt;"Now we have gotten the result from {0} with result {1}"&lt;/span&gt;, ga.AssignedTo, ga.Result.ToString());
    &lt;span class="rem"&gt;// here's where we can have some additional reasoning about why we quit&lt;/span&gt;
    &lt;span class="rem"&gt;// this is where all the "rejected cancels everyone" logic could live.&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (ga.Result == TypeOfResult.Approved)
        numApproved++;
    &lt;span class="rem"&gt;// close out the activity&lt;/span&gt;
    context.ExecutionContextManager.CompleteExecutionContext(context.ExecutionContextManager.GetExecutionContext(e.Activity));
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!approvalsCompleted  &amp;amp;&amp;amp; (numApproved &amp;gt;= NumRequired))
    {
        &lt;span class="rem"&gt;// we are done!, we only need to cancel all executing activities once&lt;/span&gt;
        approvalsCompleted = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Activity a &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetDynamicActivities(&lt;span class="kwrd"&gt;this&lt;/span&gt;.EnabledActivities[0]))
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (a.ExecutionStatus == ActivityExecutionStatus.Executing)
                context.ExecutionContextManager.GetExecutionContext(a).CancelActivity(a);
    }
    &lt;span class="rem"&gt;// are we really done with everything? we have to check so that all of the &lt;/span&gt;
    &lt;span class="rem"&gt;// canceling activities have finished cancelling&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (numProcessed == numRequested)
        context.CloseActivity();  
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Code from "OnEvent"
&lt;p&gt;The steps here, in English
&lt;ul&gt;
&lt;li&gt;UnregisterForStatusChange - we're done listening.
&lt;li&gt;Increment the number of activities which have closed (this will be used to figure out if we are done)
&lt;li&gt;Write out to the console for the sake of sanity
&lt;li&gt;If we've been approved, increment the counter tracking how many approvals we have
&lt;li&gt;Use the ExecutionContextManager to &lt;a href="http://msdn2.microsoft.com/en-us/library/ms592884.aspx"&gt;CompleteExecutionContext&lt;/a&gt;, this marks the execution context we created for the activity done.
&lt;li&gt;Now let's check if we have the right number of approvals, if we do, mark a flag so we know we're done worrying about approves and rejects and then proceed to cancel the activities. CancelActivity. &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.activityexecutioncontext.cancelactivity.aspx"&gt;CancelActivity&lt;/a&gt; schedules the cancellation, it is possible that this is not a synchronous thing (we can go idle waiting for a cancellation confirmation, for instance.
&lt;li&gt;Then we check if all of the activities have closed. What will happen once the activities are scheduled for cancellation is that each one will eventually cancel and then close. This will cause the event to be raised and we step through the above pieces again. Once every activity is done, we finally close out the activity itself.&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Using it&lt;/h3&gt;
&lt;p&gt;I placed the activity in a workflow, configured it with five approvers and set it for two to be required to move on. I also placed a code activity outputting "Ahhh, I'm done". I also put a Throw activity in there to raise an exception and cause compensation to occur to illustrate that only the two that completed are compensated for.
&lt;p&gt;&lt;img height="306" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/ImplementingtheNofMPatterninWF_F7F8/clip_image004%5B1%5D%5B1%5D_2.png" width="200"&gt;&lt;img height="353" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/ImplementingtheNofMPatterninWF_F7F8/clip_image005_1.png" width="672"&gt;
&lt;p&gt;So, what did we do?
&lt;ul&gt;
&lt;li&gt;Create a custom composite activity with the execution logic to implement an n-of-m pattern
&lt;li&gt;Saw how we can use IEventActivityListener in order to handle events raised by our child activities
&lt;li&gt;Saw how to handle potentially long running cancellation logic, and how to cancel running activities in general.
&lt;li&gt;Saw how compensation only occurs for activities that have completed successfully&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Extensions to this idea:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;More sophisticated rules surrounding the approval (if a VP or two GM's say no, we must stop)
&lt;li&gt;Non binary choices (interesting for scoring scenarios, if the average score gets above 95%, regardless of how many approvers remaining, we move on)
&lt;li&gt;Create a designer to visualize this, especially when displayed in the workflow monitor to track it
&lt;li&gt;Validation (don't let me specify 7 approvals required, and only 3 people)&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3556624" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf/default.aspx">wf</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/patterns/default.aspx">patterns</category></item><item><title>Different Execution Patterns with WF (or, Going beyond Sequential and State Machine)</title><link>http://blogs.msdn.com/mwinkle/archive/2007/05/24/different-execution-patterns-with-wf-or-going-beyond-sequential-and-state-machine.aspx</link><pubDate>Fri, 25 May 2007 00:34:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2850983</guid><dc:creator>mwinkle</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/2850983.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=2850983</wfw:commentRss><description>&lt;h2&gt;How do I do this? &lt;/h2&gt; &lt;p align="center"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image.png" atomicselection="true"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="241" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_thumb.png" width="368" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;A lot of times people get stuck with the impression that there are only two workflow models available: sequential and state machine. True, out of the box these are the two that are built in, but only because there are is a set of common problems that map nicely into their execution semantics. As a result of these two being "in the box," I often see people doing a lot of very unnatural things in order to fit their problem into a certain model.  &lt;p&gt;The drawing above illustrates the flow of one such pattern. In this case, the customer wanted parallel execution with two branches ((1,3) and (2,5)). But, they had an additional factor that played in here, 4 could execute, but it could only execute when both 1 and 2 had completed. 4 didn't need to wait for 3 and 5 to finish, 3 and 5 could take a long period of time, so 4 could at least start once 1 and 2 were completed. Before we dive into a more simple solution, let's look at some of the ways they tried to solve the problem, in an attempt to use "what's in the box."  &lt;h3&gt;The "While-polling" approach &lt;/h3&gt; &lt;p align="center"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_1.png" atomicselection="true"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="287" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_thumb_1.png" width="359" align="left" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;  &lt;p&gt;The basic idea behind this approach is that we will use a parallel activity, and in the third branch we will place a while loop that loops on the condition of "if activity x is done" with a brief delay activity in there so that we are not busy polling. What's the downside to this approach:  &lt;ul&gt; &lt;li&gt;The model is unnatural, and gets more awkward given the complexity of the process (what do we do if activity 7 has a dependency on 4 and 5)  &lt;li&gt;The polling and waiting is just not an efficient way to solve the problem  &lt;li&gt;This Is a lot to ask a developer to do in order to translate the representation she has in her head (first diagram, with the model we are forcing into).&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;The SynchScope approach &lt;/h3&gt; &lt;p&gt;WF V1 does have the idea of synchronizing some execution by using the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.synchronizationscopeactivity.aspx"&gt;SynchronizationScope&lt;/a&gt; activity. The basic idea behind the SynchronizationScope is that one can specify a set of handles that the activity must be able to acquire before allowing it's contained activities to execute. This let's us serialize access and execution. We could use this to mimic some of the behavior that the polling is doing above. We will use sigma(x, y, z) to indicate the synchronization scope and it's handles (just because I don't get to use nearly as many Greek letters as I used to).  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_2.png" atomicselection="true"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="267" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_thumb_2.png" width="514" align="right" border="0"&gt;&lt;/a&gt;  &lt;p&gt;This should work, provided the synchronization scopes can obtain the handles in the "correct" or "intended" order. Again, the downside here is that this gets to be pretty complex, how do we model 4 having a dependency on 3 and 2? Well, our first synchronization scope now needs to extend to cover the whole left branch, and then it should work. For the simple case like the process map I drew at the beginning, this will probably work, but as the dependency map gets deeper, we are going to run into more problems trying to make this work.  &lt;h2&gt;Creating a New Execution Pattern &lt;/h2&gt; &lt;p&gt;WF is intended to be a general purpose process engine, not just a sequential or state machine process engine. We can write our own process execution patterns by writing our own custom composite activity. Let's first describe what this needs to do:  &lt;ul&gt; &lt;li&gt; &lt;p&gt;Allow activities to be scheduled based on all of their dependent activities having executed.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;We will start by writing a custom activity that has a property for expressing dependencies. A more robust implementation would use &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.dependencyproperty.registerattached.aspx"&gt;attached properties&lt;/a&gt; to push those down to any contained activity&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Analyze the list of dependencies to determine which activities we can start executing (perhaps in parallel)  &lt;li&gt;When any activity completes, check where we are at and if any dependencies are now satisfied. If they are, schedule those for execution.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So, how do we go about doing this?&lt;/p&gt; &lt;h3&gt;Create a simple activity with a "Preconditions" property&lt;/h3&gt; &lt;p&gt;In the future, this will be any activity using an attached property, but I want to start small and focus on the execution logic. This one is a simple Activity with a "Preconditions" array of strings where the strings will be the names of the activities which must execute first:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SampleWithPreconProperty: Activity
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; SampleWithPreconProperty()
    {
        InitializeComponent();
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] preconditions = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[0];

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] Preconditions
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; preconditions; }
        set { preconditions = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;Create the PreConditionExecutor Activity&lt;/h3&gt;
&lt;p&gt;Let's first look at the declaration and the members:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Designer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(SequentialActivityDesigner),&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IDesigner))]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PreConditionExecutor : CompositeActivity
{
    &lt;span class="rem"&gt;// this is a dictionary of the executed activities to be indexed via&lt;/span&gt;
    &lt;span class="rem"&gt;// activity name&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt; executedActivities = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt;();

    &lt;span class="rem"&gt;// this is a dictionary of activities marked to execute (so we don't &lt;/span&gt;
    &lt;span class="rem"&gt;// try to schedule the same activity twice)&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt; markedToExecuteActivities = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt;();

    &lt;span class="rem"&gt;// dependency maps&lt;/span&gt;
    &lt;span class="rem"&gt;// currently dictionary&amp;lt;string, list&amp;lt;string&amp;gt;&amp;gt; that can be read as &lt;/span&gt;
    &lt;span class="rem"&gt;// activity x has dependencies in list a, b, c&lt;/span&gt;
    &lt;span class="rem"&gt;// A more sophisticated implementation will use a graph object to track&lt;/span&gt;
    &lt;span class="rem"&gt;// execution paths and be able to check for completeness, loops, all&lt;/span&gt;
    &lt;span class="rem"&gt;// that fun graph theory stuff I haven't thought about in a while&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt; dependencyMap = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;();
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;We have three dictionaries, one to track which have completed, one for which ones are scheduled for execution, and one to map the dependencies. As noted in the comments, a directed graph would be a better representation of this so that we could do some more sophisticated analysis on it.&lt;/p&gt;
&lt;p&gt;Now, let's look at the Execute method, the one that does all the work.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (0 == Activities.Count)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ActivityExecutionStatus.Closed;
    }
    &lt;span class="rem"&gt;// loop through the activities and mark those that have no preconditions&lt;/span&gt;
    &lt;span class="rem"&gt;// as ok to execute and put those in the queue&lt;/span&gt;
    &lt;span class="rem"&gt;// also generate the graph which will determine future activity execution.&lt;/span&gt;
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Activity a &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities)
    {
        &lt;span class="rem"&gt;// start with our basic activity&lt;/span&gt;
        SampleWithPreconProperty preconActivity = a &lt;span class="kwrd"&gt;as&lt;/span&gt; SampleWithPreconProperty;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; == preconActivity)
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Not right now, we're not that fancy"&lt;/span&gt;);
        }
        &lt;span class="rem"&gt;// construct the execution dictionary&lt;/span&gt;
        executedActivities.Add(a.Name, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
        markedToExecuteActivities.Add(a.Name, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
        List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; actDependencies = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != preconActivity.Preconditions)
        {
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; s &lt;span class="kwrd"&gt;in&lt;/span&gt; preconActivity.Preconditions)
            {
                actDependencies.Add(s);
            }
        }
        dependencyMap.Add(a.Name, actDependencies);
    }
    &lt;span class="rem"&gt;// now we have constructed our execution map and our dependency map&lt;/span&gt;
    &lt;span class="rem"&gt;// let's do something with those, like find those activities with&lt;/span&gt;
    &lt;span class="rem"&gt;// no dependencies and schedule those for execution.&lt;/span&gt;
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Activity a &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (0 == dependencyMap[a.Name].Count)
        {
            Activity executeThis = &lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities[a.Name];
            executeThis.Closed += currentlyExecutingActivity_Closed;
            markedToExecuteActivities[a.Name] = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            executionContext.ExecuteActivity(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities[a.Name]);
            Console.WriteLine(&lt;span class="str"&gt;"Scheduled: {0}"&lt;/span&gt;, a.Name);
        }
    }
    &lt;span class="kwrd"&gt;return&lt;/span&gt; ActivityExecutionStatus.Executing;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Basically, we first construct the execution tracking dictionaries, initializing those to false. We then create the dictionary of dependencies. We then loop through the activities and see if there are any that have no dependencies (there has to be one, this would be a good point to raise an exception if there isn't. We record in the dictionary that this one has been marked to execute and then we schedule it for execution (after hooking the Closed event so that we can do some more work later). So what happens when we close?&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; currentlyExecutingActivity_Closed(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, ActivityExecutionStatusChangedEventArgs e)
{
    e.Activity.Closed -= &lt;span class="kwrd"&gt;this&lt;/span&gt;.currentlyExecutingActivity_Closed;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecutionStatus == ActivityExecutionStatus.Canceling)
    {
        ActivityExecutionContext context = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; ActivityExecutionContext;
        context.CloseActivity();
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecutionStatus == ActivityExecutionStatus.Executing)
    {
        &lt;span class="rem"&gt;// set the Executed Dictionary&lt;/span&gt;
        executedActivities[e.Activity.Name] = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (executedActivities.ContainsValue(&lt;span class="kwrd"&gt;false&lt;/span&gt;) &lt;span class="rem"&gt;/* keep going */&lt;/span&gt;)
        {
            &lt;span class="rem"&gt;// find all the activities that contain the precondition &lt;/span&gt;
            &lt;span class="rem"&gt;// and remove them, and then cycle through any that have 0 &lt;/span&gt;
            &lt;span class="rem"&gt;// preconditions (and have not already executed or are marked&lt;/span&gt;
            &lt;span class="rem"&gt;// to execute&lt;/span&gt;
            &lt;span class="rem"&gt;// who contains this precondition? &lt;/span&gt;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Activity a &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Activities)
            {
                &lt;span class="rem"&gt;// filter out those activities executed or executing&lt;/span&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!(executedActivities[a.Name] || markedToExecuteActivities[a.Name]))
                {
                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (dependencyMap[a.Name].Contains(e.Activity.Name))
                    {
                        &lt;span class="rem"&gt;// we found it, remove it&lt;/span&gt;
                        dependencyMap[a.Name].Remove(e.Activity.Name);
                        &lt;span class="rem"&gt;// if we now have no dependencies, let's schedule it&lt;/span&gt;
                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (0 == dependencyMap[a.Name].Count)
                        {
                            a.Closed += currentlyExecutingActivity_Closed;
                            ActivityExecutionContext context = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; ActivityExecutionContext;
                            markedToExecuteActivities[a.Name] = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
                            context.ExecuteActivity(a);
                            Console.WriteLine(&lt;span class="str"&gt;"Scheduled: {0}"&lt;/span&gt;, a.Name);
                        }
                    }
                }
            }
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="rem"&gt;//close activity&lt;/span&gt;
        {
            ActivityExecutionContext context = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; ActivityExecutionContext;
            context.CloseActivity();
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are a few lines of code here, but it's pretty simple what's going on. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We remove the event handler 
&lt;li&gt;If we're still executing, mark the list of activities appropriately 
&lt;li&gt;Loop through and see if any of them have dependencies on the activity which just now completed being done 
&lt;li&gt;If they do, remove that entry from the dependency list and check if we can run it (if the count == 0). If we can, schedule it, otherwise keep looping. 
&lt;li&gt;If all the activities have completed (there is no false in the Executed list) then we will close out this activity.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;To actually use this activity, we place it in the workflow, place a number of the child activity types within it (again, with the attached property, you could put nearly any activity in there) and specify the activities that it depends on. Since I haven't put a designer on it, I just use the SequenceDesigner. Here's what it looks like (this is like the graph I drew above but kicks off with the "one" activity executing first:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_3.png" atomicselection="true"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="451" alt="image" src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DifferentExecutionPatternswithWForGoingb_CCEE/image_thumb_3.png" width="722" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Where can we go from here &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Validation, remember all that fun graph theory stuff checking for cycles and completeness and no gaps. Yeah, we should probably wire some of that stuff up here to make sure we can actually execute this thing 
&lt;li&gt;Analysis of this might be interesting, especially as the process gets more complex (identifying complex dependencies, places for optimization, capacity stuff) 
&lt;li&gt;A designer to actually do all of this automatically. Right now, it is left as an exercise to the developer to express the dependencies by way of the properties. It would be nice to have a designer that would figure that out for you, and also validate so you don't try to do the impossible.
&lt;li&gt;Make this much more dynamic and pull in the preconditions and generate the context for the activities on the fly.&amp;nbsp; This would be cool if you had a standard "approval" activity that you wanted to have a more configurable execution pattern.&amp;nbsp; You could build the graph through the designer and then use that to drive the execution&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;I'm going to hold off on posting the code, as I've got a few of these and I'd like to come up with some way to put them out there that would make it easy to get to them and use them. You should be able to pretty easily construct your own activity based on the code presented here.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2850983" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf/default.aspx">wf</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/patterns/default.aspx">patterns</category></item><item><title>Dynamically Generating an Operation Contract in Orcas using WF</title><link>http://blogs.msdn.com/mwinkle/archive/2007/04/27/dynamically-generating-an-operation-contract-in-orcas.aspx</link><pubDate>Fri, 27 Apr 2007 19:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2300995</guid><dc:creator>mwinkle</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/2300995.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=2300995</wfw:commentRss><description>&lt;p&gt;This kicks off a set of posts where I'll be discussing some of the interesting features coming out in Orcas.&lt;/p&gt; &lt;p&gt;I want to focus on this post on the Receive Activity, and a nice little feature in the designer that lets you create a contract on the fly, without having to drop into code and write a decorated interface.&amp;nbsp; This allows us to divide the world into two approaches:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;One where I design my contract first, and then start creating a workflow to implement the operations on the contract.&lt;/li&gt; &lt;li&gt;Design my workflow first, and have&amp;nbsp;it figure out the contract for me (this is what I will focus on in more detail)&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Designing a Contract First&lt;/h2&gt; &lt;p&gt;This is what most WCF folks will be familiar with:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[ServiceContract]&lt;br&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IOrderProcessing&lt;br&gt;{&lt;br&gt;&lt;br&gt;    [OperationContract]&lt;br&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; SubmitOrder(Order order);&lt;br&gt;&lt;br&gt;    [OperationContract]&lt;br&gt;    Order[] GetOrders(&lt;span class="kwrd"&gt;int&lt;/span&gt; customerId);&lt;br&gt;}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;When I drop a receive activity onto a workflow, I can now import this contract:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog1%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog1%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog1_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog1_thumb%5B1%5D.jpg" height="351" width="347"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This will bring up a type chooser that lets me pick my service contract:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog2%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog2%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog2_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog2_thumb%5B1%5D.jpg" height="390" width="513"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This imports all of the details and we can see the the operation picker&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog3%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog3%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog3_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog3_thumb%5B1%5D.jpg" height="392" width="397"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;If we look at the activity properties we now see the parameters to the method.&amp;nbsp; The (ReturnValue) is the object that we need to return in the operation.&amp;nbsp; The order parameter is the message that is going to be passed when the method is called.&amp;nbsp; I can take that and bind that to values in my workflow or whatever I want to do with it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog4%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog4%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog4_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog4_thumb%5B1%5D.jpg" height="270" width="425"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Designing a Workflow First&lt;/h2&gt;
&lt;p&gt;The other approach we can take is to create the contract as we create the workflow.&amp;nbsp; That's right, we don't need to create the contract explicitly in code.&amp;nbsp; To do that, drop a receive activity onto the designer and double click.&amp;nbsp; Instead of selecting "Import Contract" select "Add Contract".&amp;nbsp; This will create a new contract with a basic operation.&amp;nbsp; By selecting the contract or the operation we can name it something a little nicer.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog5%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog5%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog5_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog5_thumb%5B1%5D.jpg" height="435" width="424"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;By selecting the operation, I can customize all of its behavior.&amp;nbsp; I can create parameters to be passed in, I can set the types of those parameters (as well as the return type of the operation).&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog6%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog6%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog6_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog6_thumb%5B1%5D.jpg" height="405" width="505"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;It's relevent to point out that I can select any type that would be valid in a WCF contract.&amp;nbsp; The drop down list displays the basic types, but by selecting "Browse Type" I am brought into a type picker where I can select custom types.&amp;nbsp; As you can see below I have created a "CancelOrder" operation that takes in an order, the reason and who authorized the cancellation.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog7%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog7%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog7_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog7_thumb%5B1%5D.jpg" height="260" width="512"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;When I click ok, my activity has had new dependency properties added to it, as can be seen in the property grid for the activity.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog8%5B3%5D.jpg" mce_href="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog8%5B3%5D.jpg" atomicselection="true"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog8_thumb%5B1%5D.jpg" mce_src="http://blogs.msdn.com/blogfiles/mwinkle/WindowsLiveWriter/DynamicallyGeneratinganOperationContract_88F3/blog8_thumb%5B1%5D.jpg" height="324" width="445"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;So what's happening here?&lt;/h2&gt;
&lt;p&gt;In the workflow I created, I used a code separation workflow, so I have an&amp;nbsp;.xoml file which contains the workflow definition.&amp;nbsp; Let's take a quick peek at how the receive activity is defined (note, some of the xml is truncated, if you view in an rss reader or copy and past you can see all the details, I'll work on updating the blog layout):&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:ReceiveActivity&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="receiveActivity2"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:ReceiveActivity.ServiceOperationInfo&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationInfo&lt;/span&gt; &lt;span class="attr"&gt;PrincipalPermissionRole&lt;/span&gt;&lt;span class="kwrd"&gt;="administrators"&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="CancelOrder"&lt;/span&gt; &lt;span class="attr"&gt;ContractName&lt;/span&gt;&lt;span class="kwrd"&gt;="MyContract"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationInfo.Parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationParameterInfo&lt;/span&gt; &lt;span class="attr"&gt;Attributes&lt;/span&gt;&lt;span class="kwrd"&gt;="Out, Retval"&lt;/span&gt; &lt;span class="attr"&gt;ParameterType&lt;/span&gt;&lt;span class="kwrd"&gt;="{x:Type p9:Boolean}"&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="(ReturnValue)"&lt;/span&gt; &lt;span class="attr"&gt;Position&lt;/span&gt;&lt;span class="kwrd"&gt;="-1"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:p9&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationParameterInfo&lt;/span&gt; &lt;span class="attr"&gt;Attributes&lt;/span&gt;&lt;span class="kwrd"&gt;="In"&lt;/span&gt; &lt;span class="attr"&gt;ParameterType&lt;/span&gt;&lt;span class="kwrd"&gt;="{x:Type p9:Order}"&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="order"&lt;/span&gt; &lt;span class="attr"&gt;Position&lt;/span&gt;&lt;span class="kwrd"&gt;="0"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:p9&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:WcfServiceLibrary1;Assembly=WcfServiceLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationParameterInfo&lt;/span&gt; &lt;span class="attr"&gt;Attributes&lt;/span&gt;&lt;span class="kwrd"&gt;="In"&lt;/span&gt; &lt;span class="attr"&gt;ParameterType&lt;/span&gt;&lt;span class="kwrd"&gt;="{x:Type p9:String}"&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="reason"&lt;/span&gt; &lt;span class="attr"&gt;Position&lt;/span&gt;&lt;span class="kwrd"&gt;="1"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:p9&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationParameterInfo&lt;/span&gt; &lt;span class="attr"&gt;Attributes&lt;/span&gt;&lt;span class="kwrd"&gt;="In"&lt;/span&gt; &lt;span class="attr"&gt;ParameterType&lt;/span&gt;&lt;span class="kwrd"&gt;="{x:Type p9:String}"&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="authorizedBy"&lt;/span&gt; &lt;span class="attr"&gt;Position&lt;/span&gt;&lt;span class="kwrd"&gt;="2"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:p9&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationInfo.Parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ns0:OperationInfo&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ns0:ReceiveActivity.ServiceOperationInfo&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ns0:ReceiveActivity&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Here you can see that within the metadata of the activity, we have the definition for the contract and the operation that I defined.&amp;nbsp; When we spin up a WorkflowServiceHost to host this workflow as a service, the host will inspect the metadata for the workflow, looking for all of the endpoints and will create them.&amp;nbsp; You can also see within the OperationInfo element that I am able to define the PrincipalPermissionRole defining the role of allowed callers, taking advantage of the static security checks which I will talk about in another post.&amp;nbsp; So, defined declaratively in the XAML is the contract for the operations.&amp;nbsp; I didn't need to write the interface or the contract explicitly, I was able to write a workflow, specifiy in the workflow how it will communicate and then let the WorkflowServiceHost figure out the nitty gritty details of how create the endpoints.&amp;nbsp; The other part here that is important to mention is that the config will play a part determining what the transport channel and other such details will be.&amp;nbsp; Within the config, when we set up an endpoint we need to specify the contract is "MyContract", or the name that we assigned when we created it.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;We talked about the way that we can implement contracts that already exist in a receive activity, as well as how we can use the designer to actually create our contract while we are designing the workflow.&amp;nbsp; The WorkflowServiceHost does the heavy lifting here in order to enable this little bit of nifty-ness. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2300995" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf/default.aspx">wf</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/Orcas/default.aspx">Orcas</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Mechanical Turk Activities</title><link>http://blogs.msdn.com/mwinkle/archive/2007/02/07/mechanical-turk-activities.aspx</link><pubDate>Wed, 07 Feb 2007 21:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1620855</guid><dc:creator>mwinkle</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwinkle/comments/1620855.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwinkle/commentrss.aspx?PostID=1620855</wfw:commentRss><description>&lt;P&gt;Mark Blomsma has put together some activities and an article which shows how to interact with Amazon's &lt;A class="" href="http://www.mturk.com/mturk/welcome" mce_href="http://www.mturk.com/mturk/welcome"&gt;Mechanical Turk&lt;/A&gt; with WF activities.&lt;/P&gt;
&lt;P&gt;I've linked to the sample on &lt;A class="" href="http://wf.netfx3.com/files/folders/web_services/entry8710.aspx" mce_href="http://wf.netfx3.com/files/folders/web_services/entry8710.aspx"&gt;here.&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Cool, cool, cool&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1620855" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mwinkle/archive/tags/wf/default.aspx">wf</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/activities/default.aspx">activities</category><category domain="http://blogs.msdn.com/mwinkle/archive/tags/web+services/default.aspx">web services</category></item></channel></rss>