Saturday, April 28, 2007

Microsoft has gone to great lengths to keep you from touching your instance directly, forcing you to always use the workflowinstance class to manipulate your workflow from the outside. They have done this to make sure the integrity of the system is maintained. It is however, a major pain in the ass. ;-)
I have been looking into solving a serious deficiency of windows workflow foundation: updating current workflows in your database. Microsoft does not have a good story on that one, and the WF architecture seems to be designed to make it as hard as possible to actually pull off! One approach to do this, would be to get to your instance, use reflection to get to private and public fields and create your new type, setting those fields as you go. Therefor, I have been looking into getting to my persisted instance.

Please be very careful with the following technique. Do not use it lightly, because it does allow you to do things that will break the integrity. It _will_ get you into trouble, if you do not watch out.


We are going to fetch a persisted workflow, but do not want the workflow runtime interfering. So:

Database db = DatabaseFactory.CreateDatabase("##Your database##");
byte[] act = (byte[])db.ExecuteScalar(CommandType.Text,
"select state from InstanceState where uidInstanceID = '## the guid you are interested in ##'");

This will directly query your database for some guid. (I am using Entlib 3.0 here).
The byte array returned is formatted with the binaryformatter. To be able to serialize activities, the WF-team does not use the Serializable attribute, but uses surrogates. A surrogate is a class that has intimate knowledge on how to serialize a certain type. Looking at the class ActivitySurrogate, you will notice that they have quite a bit going on there. Most important seems to be the private sealed class ActivitySurrogateRef, which defines fields like these:

[NonSerialized]
private Activity cachedActivity;
[NonSerialized]
private Activity cachedDefinitionActivity;
[OptionalField]
private EventHandler disposed;
private string id = string.Empty;
[NonSerialized]
private int lastPosition;
[OptionalField]
private object memberData;
[OptionalField]
private object[] memberDatas;
[OptionalField]
private string[] memberNames;
[OptionalField]
private string rulesMarkup;
[OptionalField]
private Type type;
[OptionalField]
private string workflowChanges;
[OptionalField]
private Guid workflowChangeVersion = Guid.Empty;
[OptionalField]
private string workflowMarkup;

So, it is clear our binaryformatter is going to have to reuse this logic. Thankfully, we can use the ActivitySurrogateSelector. This selector has logic that allows it to select the correct surrogate for each type. We set it like this:

BinaryFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = ActivitySurrogateSelector.Default;

Now it is time to deserialize our byte array. However, it is zipped!! So, let's unzip it:

MemoryStream stream = new MemoryStream(act);
stream.Position = 0;
using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress, true))
{ // here we can finally deserialize.  }

Inside that using-statement, we will deserialize. Here is the line that does the magic:

T activity = (T)Activity.Load(stream2, workflowRuntime.CreateWorkflow(typeof(T)).GetWorkflowDefinition(), formatter);

The 'T' is the type of your workflow.
I am using the static Load functionality of Activity to load. We first pass in our unzipped stream (stream2) and then we have to pass the workflowdefinition of the type we are deserializing. Finally, we are using our own formatter, with the activity surrogate attached.

Obviously, the use of the workflowruntime to get to the workflowdefinition is not pretty. Ugly even. However, I have not been able to circumvent it. Passing a null, will result in serializationexceptions.
I will update this post if I find a better way. Please leave a comment if you know of one!

I can imagine that it is useful to be able to get to your instance directly. For now, the only way to get to it, seems to be when they have to release it to the persistence store.

I hope this helps someone!

Thursday, November 25, 2010 12:43:21 PM (Romance Standard Time, UTC+01:00)
I can imagine that it is useful to be able to get to your instance directly. For now, the only way to get to it, seems to be when they have to release it to the persistence store.
Thursday, December 02, 2010 3:41:18 AM (Romance Standard Time, UTC+01:00)
the highest-grade sheepskin available<a href="http://www.wwwuggsoutlet.com">ugg outlet</a> , is the age which suitable to restore the old, the every large or small varied assortment the classical design again returned to people's line of sight, from the wind series's return, 3 rewirings went forth to battle recently to <a href="http://www.shortuggboot.com/"> Classic Short UGG</a> the Garnett ... Classic Tiffany Jewelry. Publisher: Alina008. As we all know that ...<a href="http://www.uggtallboot.net">ugg classic tall</a> is packed in cartons and Blue Ribbon is the symbol of Tiffany jewelry..
Saturday, December 04, 2010 2:45:17 AM (Romance Standard Time, UTC+01:00)
Did you hear the good information? Golf clone producers have finally closed the gap! Clone the game of golf clubs constructed with superior shafts have fun nearly similar to brand manufacturer golf game clubs by Nike, Callaway, Ping, and Taylor Made. This is certainly tremendous!



I hope you now see why clone golf game clubs are really worth buying and the fact that they are just similar to any placed of clubs. So for those who are buying a arrangement of golfing clubs then you need to seriously take into account cloned clubs, they'll provide you with all the things which you would need but at a fraction in the value!
Saturday, December 04, 2010 2:52:05 AM (Romance Standard Time, UTC+01:00)
While many many people pay an ideal deal of time improving their swing the truth is if their play golf grip is not very good then the golf club deal with will probably not strike the ball correctly as well as possibilities of producing a very good and consistent golf swing is greatly reduced. And also the Pro Golfing Type ratings make a person point unquestionably clear - Luke Donald is an extremely proficient and absolutely consistent golfer. The close result may be an inconsistent swing.
Comments are closed.