I am sure you are aware that the entire WF programming model has changed (for the better, if you ask me) under .NET 4.0. Why? Well, the first release of WF was useful, but many things were much more complex than necessary. Part of this complexity is due to the fact that the previous version of WF was code driven. While you could incorportate some markup into the mix, it was not seemless, and not the default approach of Visual Studio. Under WF 4.0, by default, your workflows are authored in XAML. WF 4.0 XAML even has the ability to embed "real code" into the markup, using [ and ] tokens. Therefore, when you are using the WF designer it is possible to configure activities using calls to external objects, via LINQ queries, or any other type of logic you would normally author in C# / VB.
Another aspect of the first release of WF which was painful was how we had to create custom properties (in code) which would map to host suppled arguments. While not impossible, WF 4.0 cleans this up quite a bit as well. As of WF 4.0, data variables are a first class citizen. You can declare aguments and variables directly on the WF designer, and use them throughout your workflow. The difference? An "argument" is a variable which allows you to capture input from the host, or return values you want to send the host. A "variable" is just that- a point of data in your workflow you want to make use of internally.
You can define arguments and variables using the identically named buttons on the workflow designer. Just like when you define a variable in code, they will have a name and type, and possibly a default value. Assume you want the host to pass you two strings, which you will use to build a LINQ query. You could begin by adding two Argument variables as seen here:

Now, if we have a Sequence activity as the first child of the root, we could make use of two WriteLine activities to print out the host suppled string data, represented by our HostStringOne and HostStringTwo variables. As well, we will use an Assign activity to set a value for our output parameter, which will be received by the host. Do be aware that a workflow can pass back any number of output paramters, so the host could get back a whole collection of information when the workflow completes.

To send arguments to the workflow, we package up name value pairs in a Dictionary<string, object> object. If we use the WorrflowInvoker.Invoke() method to spin up the workflow, the returned IDictionary<> comparable object will contain each output parameter. Consider the following Main() method which sends data to the workflow, and prints out the returned output data:
static void Main(string[] args)
{
Dictionary<string, object> wfArgs = new Dictionary<string, object>()
{
{"HostStringOne", "Testing...."},
{"HostStringTwo", "....1, 2, 3."}
};
IDictionary<string, object> retVals =
WorkflowInvoker.Invoke(new Workflow1(), wfArgs);
Console.WriteLine(retVals["DataForHost"]);
}
Notice that we pass the data to the workflow as a second argument to Invoke(). The output is as you would explect, all data displays to the console. This simple example shows one way that WF 4.0 streamlines the way we work with workflow enabled applications. If you dismissed the WF API before, I'd encourage you to take a peek at WF 4.0. It is a whole new ball game.
0c446b42-abac-4701-adab-6c967a7afc0f|0|.0