ActivitySurrogate.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Serializer / ActivitySurrogate.cs / 1305376 / ActivitySurrogate.cs

                            namespace System.Workflow.ComponentModel.Serialization 
{
 	using System;
	using System.IO;
    using System.Xml; 
	using System.Reflection;
	using System.Collections; 
 	using System.Diagnostics; 
	using System.Globalization;
 	using System.Collections.Generic; 
 	using System.Runtime.Serialization;
	using System.Runtime.Serialization.Formatters.Binary;

 	internal sealed class ActivitySurrogate : ISerializationSurrogate 
	{
		public ActivitySurrogate() 
		{ 
 		}
		public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) 
 		{
            if (Activity.ContextIdToActivityMap == null)
                throw new InvalidOperationException(SR.GetString(SR.Error_ActivitySaveLoadNotCalled));
 
 			Activity activity = (Activity)obj;
            bool isSurroundingActivity = false; 
			bool isDanglingActivity = IsDanglingActivity(activity, out isSurroundingActivity); 
 			if (isSurroundingActivity)
			{ 
				// if this object is in parent chain then replace it with token
				if (activity.ContextActivity != null)
 					info.AddValue("cid", activity.ContextId);
 
				info.AddValue("id", activity.DottedPath);
 				info.SetType(typeof(ActivityRef)); 
 			} 
			else if (!isDanglingActivity)
 			{ 
				info.AddValue("id", activity.DottedPath);

				string[] names = null;
				MemberInfo[] members = FormatterServicesNoSerializableCheck.GetSerializableMembers(obj.GetType(), out names); 
 				object[] memberDatas = FormatterServices.GetObjectData(obj, members);
                // To improve performance, we specialize the case where there are only 2 fields.  One is the 
                // instance dependency property values dictionary and the other is the "disposed" event. 
                if (memberDatas != null && memberDatas.Length == 2)
				{ 
                    Debug.Assert(members[0].Name == "dependencyPropertyValues" && members[1].Name == "disposed");
 					IDictionary instanceProperties = (IDictionary)memberDatas[0];
 					if (instanceProperties != null && instanceProperties.Count > 0)
					{ 
 						foreach (KeyValuePair kvp in instanceProperties)
						{ 
							if (kvp.Key != null && !kvp.Key.DefaultMetadata.IsNonSerialized) 
							{
 								info.AddValue("memberData", memberDatas[0]); 
								break;
 							}
 						}
					} 
                    if (memberDatas[1] != null)
                        info.AddValue("disposed", memberDatas[1]); 
                } 
 				else
				{ 
					info.AddValue("memberNames", names);
					info.AddValue("memberDatas", memberDatas);
 				}
 
				// for root activity serialize the change actions if there are any
 				if (obj is Activity && ((Activity)obj).Parent == null) 
 				{ 
                    string wMarkup = activity.GetValue(Activity.WorkflowXamlMarkupProperty) as string;
                    if (!string.IsNullOrEmpty(wMarkup)) 
                    {
                        info.AddValue("workflowMarkup", wMarkup);

                        //if we got rules in XAML Load case, serialize them as well 
                        string rMarkup = activity.GetValue(Activity.WorkflowRulesMarkupProperty) as string;
                        if (!string.IsNullOrEmpty(rMarkup)) 
                            info.AddValue("rulesMarkup", rMarkup); 
                    }
                    else 
                        info.AddValue("type", activity.GetType());

					Activity workflowDefinition = (Activity)activity.GetValue(Activity.WorkflowDefinitionProperty);
 					if (workflowDefinition != null) 
					{
						ArrayList changeActions = (ArrayList)workflowDefinition.GetValue(WorkflowChanges.WorkflowChangeActionsProperty); 
						if (changeActions != null) 
 						{
							Guid changeVersion = (Guid)workflowDefinition.GetValue(WorkflowChanges.WorkflowChangeVersionProperty); 
 							info.AddValue("workflowChangeVersion", changeVersion);
                            using (StringWriter changeActionsStringWriter = new StringWriter(CultureInfo.InvariantCulture))
                            {
                                using (XmlWriter xmlWriter = Design.Helpers.CreateXmlWriter(changeActionsStringWriter)) 
                                {
                                    new WorkflowMarkupSerializer().Serialize(xmlWriter, changeActions); 
                                    info.AddValue("workflowChanges", changeActionsStringWriter.ToString()); 
                                }
                            } 
 						}
					}
 				}
				info.SetType(typeof(ActivitySerializedRef)); 
			}
			else 
 			{ 
				info.AddValue("id", activity.Name);
 				info.AddValue("type", activity.GetType()); 
 				info.SetType(typeof(DanglingActivityRef));
			}
 		}
		public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) 
		{
			return null; 
 		} 
		private bool IsDanglingActivity(Activity activity, out bool isSurrounding)
 		{ 
 			isSurrounding = false;
			bool isDangling = false;
 			do
			{ 
				if (Activity.ActivityRoots.Contains(activity))
				{ 
 					isDangling = false; 
					break;
 				} 

 				if (activity.Parent == null)
				{
                    isDangling = ((Activity)Activity.ActivityRoots[0]).RootActivity != activity; 
 					break;
				} 
 
				if (!activity.Parent.Activities.Contains(activity))
				{ 
 					IList activeContextActivities = null;
					if (activity.Parent.ContextActivity != null)
 						activeContextActivities = (IList)activity.Parent.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty);
 
 					if (activeContextActivities == null || !activeContextActivities.Contains(activity))
					{ 
 						isDangling = true; 
						break;
					} 
				}
 				activity = activity.Parent;
			} while (activity != null);
 
            isSurrounding = (!isDangling && !Activity.ActivityRoots.Contains(activity));
 			return isDangling; 
 		} 

		[Serializable] 
 		private sealed class ActivityRef : IObjectReference
		{
			[OptionalField]
			private int		cid = 0; 
 			private string	id	= string.Empty;
 
			Object IObjectReference.GetRealObject(StreamingContext context) 
 			{
                if (Activity.ContextIdToActivityMap == null) 
                    throw new InvalidOperationException(SR.GetString(SR.Error_ActivitySaveLoadNotCalled));

 				Activity contextActivity = (Activity)Activity.ContextIdToActivityMap[this.cid];
				return contextActivity.TraverseDottedPathFromRoot(this.id); 
 			}
		} 
 
		[Serializable]
		private sealed class ActivitySerializedRef : IObjectReference, IDeserializationCallback 
 		{
			private string		id				= string.Empty;

 			[OptionalField] 
 			private object		memberData		= null;
			 
            [OptionalField] 
 			private object[]	memberDatas		= null;
			 
            [OptionalField]
			private string[]	memberNames		= null;
			
            [OptionalField] 
 			private Type		type			= null;
 
            [OptionalField] 
			private string		workflowMarkup	= null;
 
            [OptionalField]
            private string      rulesMarkup = null;

 			[OptionalField] 
 			private string		workflowChanges = null;
			 
            [OptionalField] 
 			private Guid		workflowChangeVersion = Guid.Empty;
 
            [OptionalField]
            private EventHandler disposed = null;

            [NonSerialized] 
			private Activity	cachedDefinitionActivity = null;
 
			[NonSerialized] 
			private Activity	cachedActivity = null;
 
 			[NonSerialized]
			private int		lastPosition = 0;

 			object IObjectReference.GetRealObject(StreamingContext context) 
 			{
				// if definition activity has not been yet deserialized then return null 
                if (Activity.DefinitionActivity == null) 
                {
                    if (this.type == null && string.IsNullOrEmpty(this.workflowMarkup)) 
                        return null;

                    Activity rootActivityDefinition = null;
                    // We always call into runtime to resolve an activity.  The runtime may return an existing cached workflow definition 
                    // or it may return a new one if none exists.
                    // When we have dynamic updates, we ask runtime to always return us a new instance of the workflow definition. 
                    // This new instance should not be initialized for runtime.  We must apply workflow changes first 
                    // before we initialize it for runtime.
                    bool createNewDef = (this.workflowChanges != null); 
                    rootActivityDefinition = Activity.OnResolveActivityDefinition(this.type, this.workflowMarkup, this.rulesMarkup, createNewDef, !createNewDef, null);
                    if (rootActivityDefinition == null)
                        throw new NullReferenceException(SR.GetString(SR.Error_InvalidRootForWorkflowChanges));
 
                    if (createNewDef)
                    { 
                        ArrayList changeActions = Activity.OnResolveWorkflowChangeActions(this.workflowChanges, rootActivityDefinition); 
                        foreach (WorkflowChangeAction changeAction in changeActions)
                        { 
                            bool result = changeAction.ApplyTo(rootActivityDefinition);
                            Debug.Assert(result, "ApplyTo failed");
                        }
 
                        rootActivityDefinition.SetValue(WorkflowChanges.WorkflowChangeActionsProperty, changeActions);
                        rootActivityDefinition.SetValue(WorkflowChanges.WorkflowChangeVersionProperty, this.workflowChangeVersion); 
                        ((IDependencyObjectAccessor)rootActivityDefinition).InitializeDefinitionForRuntime(null); 
                    }
 
 					// assign it over to the thread static guy so others can access it as well.
                    Activity.DefinitionActivity = rootActivityDefinition;
                }
 
				if (this.cachedActivity == null)
				{ 
					this.cachedDefinitionActivity = Activity.DefinitionActivity.TraverseDottedPathFromRoot(this.id); 
 					this.cachedActivity = (Activity)FormatterServices.GetUninitializedObject(this.cachedDefinitionActivity.GetType());
				} 
 				return this.cachedActivity;
 			}
			void IDeserializationCallback.OnDeserialization(object sender)
 			{ 
				if (this.cachedActivity != null)
				{ 
                    bool done = false; 
					string[] currentMemberNames = null;
 					MemberInfo[] members = FormatterServicesNoSerializableCheck.GetSerializableMembers(this.cachedActivity.GetType(), out currentMemberNames); 
					if (members.Length == 2)
 					{
                        Debug.Assert(members[0].Name == "dependencyPropertyValues" && members[1].Name == "disposed");
                        // To improve performance, we specialize the case where there are only 2 fields.  One is the 
                        // instance dependency property values dictionary and the other is the "disposed" event.
                        if (this.memberData != null && this.disposed != null) 
                        { 
                            FormatterServices.PopulateObjectMembers(this.cachedActivity, members, new object[] { this.memberData, this.disposed });
                            done = true; 
                        }
                        else if (this.memberData != null)
                        {
                            FormatterServices.PopulateObjectMembers(this.cachedActivity, new MemberInfo[] { members[0] }, new object[] { this.memberData }); 
                            done = true;
                        } 
                        else if (this.disposed != null) 
                        {
                            FormatterServices.PopulateObjectMembers(this.cachedActivity, new MemberInfo[] { members[1] }, new object[] { this.disposed }); 
                            done = true;
                        }
 					}
					 
                    if (!done && this.memberDatas != null)
 					{ 
						// re-order the member datas if needed 
						Object[] currentMemberDatas = new object[members.Length];
						for( int index = 0; index < currentMemberNames.Length; index++) 
 							currentMemberDatas[index] = this.memberDatas[Position(currentMemberNames[index])];
						
 						// populate the object
 						FormatterServices.PopulateObjectMembers(this.cachedActivity, members, currentMemberDatas); 
					}
 					this.cachedActivity.FixUpMetaProperties(this.cachedDefinitionActivity); 
					this.cachedActivity = null; 
				}
			} 
 			private int Position(String name)
			{
 				if (this.memberNames.Length > 0 && this.memberNames[this.lastPosition].Equals(name))
 				{ 
					return this.lastPosition;
 				} 
				else if ((++this.lastPosition < this.memberNames.Length) && (this.memberNames[this.lastPosition].Equals(name))) 
				{
					return this.lastPosition; 
 				}
				else
 				{
 					// Search for name 
					for (int i = 0; i < this.memberNames.Length; i++)
 					{ 
						if (this.memberNames[i].Equals(name)) 
						{
							this.lastPosition = i; 
 							return this.lastPosition;
						}
 					}
 
 					//throw new SerializationException(String.Format(Environment.GetResourceString("Serialization_MissingMember"),name,objectType));
					this.lastPosition = 0; 
 					return -1; 
				}
			} 
		}
 		[Serializable]
		private class DanglingActivityRef : IObjectReference
 		{ 
 			private string	id = string.Empty;
			private Type	type = null; 
 
 			[NonSerialized]
			private Activity activity = null; 

			object IObjectReference.GetRealObject(StreamingContext context)
			{
 				if (this.activity == null) 
				{
 					// meta properties and other instance properties, parent-child relation ships are lost 
 					this.activity = (Activity)Activator.CreateInstance(this.type); 
					this.activity.Name = this.id;
 				} 
				return this.activity;
			}
		}
 	} 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK