Interop.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 / RunTime / System / Activities / Statements / Interop.cs / 1305376 / Interop.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.Activities.Statements 
{
    using System.Activities; 
    using System.Activities.Expressions; 
    using System.Activities.Persistence;
    using System.Activities.Tracking; 
    using System.Activities.Validation;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Linq; 
    using System.Reflection;
    using System.Threading;
    using System.Transactions;
    using System.Xml.Linq; 
    using System.Workflow.Runtime;
    using System.Workflow.ComponentModel.Compiler; 
    using ValidationError = System.Activities.Validation.ValidationError; 
    using System.Workflow.Runtime.Hosting;
    using System.Workflow.Activities; 
    using System.Runtime.Serialization;

    [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces",
        Justification = "The type name 'Interop' conflicts in whole or in part with the namespace name 'System.Web.Services.Interop' - not common usage")] 
    public sealed class Interop : NativeActivity, ICustomTypeDescriptor
    { 
        static Func getDefaultTimerExtension = new Func(GetDefaultTimerExtension); 
        static Func getInteropPersistenceParticipant = new Func(GetInteropPersistenceParticipant);
        Dictionary properties; 
        Dictionary metaProperties;
        System.Workflow.ComponentModel.Activity v1Activity;
        IList outputPropertyDefinitions;
        HashSet extraDynamicArguments; 
        bool exposedBodyPropertiesCacheIsValid;
        IList exposedBodyProperties; 
        Variable interopActivityExecutor; 
        Variable runtimeTransactionHandle;
        BookmarkCallback onResumeBookmark; 
        CompletionCallback onPersistComplete;
        BookmarkCallback onTransactionComplete;
        Type activityType;
        Persist persistActivity; 

        internal const string InArgumentSuffix = "In"; 
        internal const string OutArgumentSuffix = "Out"; 
        Variable persistOnClose;
        Variable interopEnlistment; 
        Variable outstandingException;

        object thisLock;
        // true if the body type is a valid activity. used so we can have delayed validation support in the designer 
        bool hasValidBody;
        // true if the V3 activity property names will conflict with our generated argument names 
        bool hasNameCollision; 

        public Interop() 
            : base()
        {
            this.interopActivityExecutor = new Variable();
            this.runtimeTransactionHandle = new Variable(); 
            this.persistOnClose = new Variable();
            this.interopEnlistment = new Variable(); 
            this.outstandingException = new Variable(); 
            this.onResumeBookmark = new BookmarkCallback(this.OnResumeBookmark);
            this.persistActivity = new Persist(); 
            this.thisLock = new object();
            base.Constraints.Add(ProcessAdvancedConstraints());
        }
 
        [DefaultValue(null)]
        public Type ActivityType 
        { 
            get
            { 
                return this.activityType;
            }
            set
            { 
                if (value != this.activityType)
                { 
                    this.hasValidBody = false; 
                    if (value != null)
                    { 
                        if (typeof(System.Workflow.ComponentModel.Activity).IsAssignableFrom(value)
                            && value.GetConstructor(Type.EmptyTypes) != null)
                        {
                            this.hasValidBody = true; 
                        }
                    } 
 
                    this.activityType = value;
 
                    if (this.metaProperties != null)
                    {
                        this.metaProperties.Clear();
                    } 
                    if (this.outputPropertyDefinitions != null)
                    { 
                        this.outputPropertyDefinitions.Clear(); 
                    }
                    if (this.properties != null) 
                    {
                        this.properties.Clear();
                    }
                    if (this.exposedBodyProperties != null) 
                    {
                        for (int i = 0; i < this.exposedBodyProperties.Count; i++) 
                        { 
                            this.exposedBodyProperties[i].Invalidate();
                        } 
                        this.exposedBodyProperties.Clear();
                    }
                    this.exposedBodyPropertiesCacheIsValid = false;
 
                    this.v1Activity = null;
                } 
            } 
        }
 
        [Browsable(false)]
        public IDictionary ActivityProperties
        {
            get 
            {
                if (this.properties == null) 
                { 
                    this.properties = new Dictionary();
                } 

                return this.properties;
            }
        } 

        [Browsable(false)] 
        public IDictionary ActivityMetaProperties 
        {
            get 
            {
                if (this.metaProperties == null)
                {
                    this.metaProperties = new Dictionary(); 
                }
                return this.metaProperties; 
            } 
        }
 
        protected override bool CanInduceIdle
        {
            get
            { 
                return true;
            } 
        } 

        internal System.Workflow.ComponentModel.Activity ComponentModelActivity 
        {
            get
            {
                if (this.v1Activity == null && this.ActivityType != null) 
                {
                    Debug.Assert(this.hasValidBody, "should only be called when we have a valid body"); 
                    this.v1Activity = CreateActivity(); 
                }
                return this.v1Activity; 
            }
        }

        internal IList OutputPropertyDefinitions 
        {
            get 
            { 
                return this.outputPropertyDefinitions;
            } 
        }

        internal bool HasNameCollision
        { 
            get
            { 
                return this.hasNameCollision; 
            }
        } 

        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
            if (this.extraDynamicArguments != null) 
            {
                this.extraDynamicArguments.Clear(); 
            } 

            this.v1Activity = null; 

            if (this.hasValidBody)
            {
                //Cache the output properties prop info for look up. 
                this.outputPropertyDefinitions = new List();
 
                //Cache the extra property definitions for look up in OnOpen 
                if (this.properties != null)
                { 
                    if (this.extraDynamicArguments == null)
                    {
                        this.extraDynamicArguments = new HashSet();
                    } 

                    foreach (string name in properties.Keys) 
                    { 
                        this.extraDynamicArguments.Add(name);
                    } 
                }

                //Create matched pair of RuntimeArguments for every property: Property (InArgument) & PropertyOut (Argument)
                PropertyInfo[] bodyProperties = this.ActivityType.GetProperties(); 
                // recheck for name collisions
                this.hasNameCollision = InteropEnvironment.ParameterHelper.HasPropertyNameCollision(bodyProperties); 
                foreach (PropertyInfo propertyInfo in bodyProperties) 
                {
                    if (InteropEnvironment.ParameterHelper.IsBindable(propertyInfo)) 
                    {
                        string propertyInName;
                        //If there are any Property/PropertyOut name pairs already extant, we fall back to renaming the InArgument half of the pair as well
                        if (this.hasNameCollision) 
                        {
                            propertyInName = propertyInfo.Name + Interop.InArgumentSuffix; 
                        } 
                        else
                        { 
                            propertyInName = propertyInfo.Name;
                        }
                        //We always rename the OutArgument half of the pair
                        string propertyOutName = propertyInfo.Name + Interop.OutArgumentSuffix; 

                        RuntimeArgument inArgument = new RuntimeArgument(propertyInName, propertyInfo.PropertyType, ArgumentDirection.In); 
                        RuntimeArgument outArgument = new RuntimeArgument(propertyOutName, propertyInfo.PropertyType, ArgumentDirection.Out); 

                        if (this.properties != null) 
                        {
                            Argument inBinding = null;
                            if (this.properties.TryGetValue(propertyInName, out inBinding))
                            { 
                                if (inBinding.Direction != ArgumentDirection.In)
                                { 
                                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropArgumentDirectionMismatch, propertyInName, propertyOutName)); 
                                }
 
                                this.extraDynamicArguments.Remove(propertyInName);
                                metadata.Bind(inBinding, inArgument);
                            }
 
                            Argument outBinding = null;
                            if (this.properties.TryGetValue(propertyOutName, out outBinding)) 
                            { 
                                this.extraDynamicArguments.Remove(propertyOutName);
                                metadata.Bind(outBinding, outArgument); 
                            }
                        }
                        metadata.AddArgument(inArgument);
                        metadata.AddArgument(outArgument); 

                        this.outputPropertyDefinitions.Add(propertyInfo); 
                    } 
                }
            } 

            metadata.SetImplementationVariablesCollection(
                new Collection
                { 
                    this.interopActivityExecutor,
                    this.runtimeTransactionHandle, 
                    this.persistOnClose, 
                    this.interopEnlistment,
                    this.outstandingException 
                });

            metadata.AddImplementationChild(this.persistActivity);
 
            if (!this.hasValidBody)
            { 
                if (this.ActivityType == null) 
                {
                    metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropBodyNotSet, this.DisplayName)); 
                }
                else
                {
                    // Body needs to be a WF 3.0 activity 
                    if (!typeof(System.Workflow.ComponentModel.Activity).IsAssignableFrom(this.ActivityType))
                    { 
                        metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropWrongBody, this.DisplayName)); 
                    }
 
                    // and have a default ctor
                    if (this.ActivityType.GetConstructor(Type.EmptyTypes) == null)
                    {
                        metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropBodyMustHavePublicDefaultConstructor, this.DisplayName)); 
                    }
                } 
            } 
            else
            { 
                if (this.extraDynamicArguments != null && this.extraDynamicArguments.Count > 0)
                {
                    metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.AttemptToBindUnknownProperties, this.DisplayName, this.extraDynamicArguments.First()));
                } 
                else
                { 
                    try 
                    {
                        InitializeMetaProperties(this.ComponentModelActivity); 
                        // We call InitializeDefinitionForRuntime in the first call to execute to
                        // make sure it only happens once.
                    }
                    catch (InvalidOperationException e) 
                    {
                        metadata.AddValidationError(e.Message); 
                    } 
                }
            } 

            metadata.AddDefaultExtensionProvider(getDefaultTimerExtension);
            metadata.AddDefaultExtensionProvider(getInteropPersistenceParticipant);
        } 

        static TimerExtension GetDefaultTimerExtension() 
        { 
            return new DurableTimerExtension();
        } 

        static InteropPersistenceParticipant GetInteropPersistenceParticipant()
        {
            return new InteropPersistenceParticipant(); 
        }
 
        protected override void Execute(NativeActivityContext context) 
        {
            // 


            WorkflowRuntimeService workflowRuntimeService = context.GetExtension();
            if (workflowRuntimeService != null && !(workflowRuntimeService is ExternalDataExchangeService)) 
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropWorkflowRuntimeServiceNotSupported)); 
            } 

            lock (this.thisLock) 
            {
                ((System.Workflow.ComponentModel.IDependencyObjectAccessor)this.ComponentModelActivity).InitializeDefinitionForRuntime(null);
            }
            if (!this.ComponentModelActivity.Enabled) 
            {
                return; 
            } 

            System.Workflow.ComponentModel.Activity activityInstance = CreateActivity(); 
            InitializeMetaProperties(activityInstance);
            activityInstance.SetValue(WorkflowExecutor.WorkflowInstanceIdProperty, context.WorkflowInstanceId);

            InteropExecutor interopExecutor = new InteropExecutor(context.WorkflowInstanceId, activityInstance, this.OutputPropertyDefinitions, this.ComponentModelActivity); 

            if (!interopExecutor.HasCheckedForTrackingParticipant) 
            { 
                interopExecutor.TrackingEnabled = (context.GetExtension() != null);
                interopExecutor.HasCheckedForTrackingParticipant = true; 
            }

            this.interopActivityExecutor.Set(context, interopExecutor);
 
            //Register the Handle as an execution property so that we can call GetCurrentTransaction or
            //RequestTransactionContext on it later 
            RuntimeTransactionHandle runtimeTransactionHandle = this.runtimeTransactionHandle.Get(context); 
            context.Properties.Add(runtimeTransactionHandle.ExecutionPropertyName, runtimeTransactionHandle);
 
            try
            {
                using (new ServiceEnvironment(activityInstance))
                { 
                    using (InteropEnvironment interopEnvironment = new InteropEnvironment(
                        interopExecutor, context, 
                        this.onResumeBookmark, 
                        this,
                        runtimeTransactionHandle.GetCurrentTransaction(context))) 
                    {
                        interopEnvironment.Execute(this.ComponentModelActivity, context);
                    }
                } 
            }
            catch(Exception exception) 
            { 
                if(WorkflowExecutor.IsIrrecoverableException(exception) || !this.persistOnClose.Get(context))
                { 
                    throw;
                }

                // We are not ----ing the exception.  The exception is saved in this.outstandingException. 
                // We will throw the exception from OnPersistComplete.
            } 
        } 

        protected override void Cancel(NativeActivityContext context) 
        {
            InteropExecutor interopExecutor = this.interopActivityExecutor.Get(context);

            if (!interopExecutor.HasCheckedForTrackingParticipant) 
            {
                interopExecutor.TrackingEnabled = (context.GetExtension() != null); 
                interopExecutor.HasCheckedForTrackingParticipant = true; 
            }
 
            interopExecutor.EnsureReload(this);

            try
            { 
                using (InteropEnvironment interopEnvironment = new InteropEnvironment(
                    interopExecutor, context, 
                    this.onResumeBookmark, 
                    this,
                    this.runtimeTransactionHandle.Get(context).GetCurrentTransaction(context))) 
                {
                    interopEnvironment.Cancel();
                }
            } 
            catch (Exception exception)
            { 
                if (WorkflowExecutor.IsIrrecoverableException(exception) || !this.persistOnClose.Get(context)) 
                {
                    throw; 
                }

                // We are not ----ing the exception.  The exception is saved in this.outstandingException.
                // We will throw the exception from OnPersistComplete. 
            }
        } 
 
        internal void SetOutputArgumentValues(IDictionary outputs, NativeActivityContext context)
        { 
            if ((this.properties != null) && (outputs != null))
            {
                foreach (KeyValuePair output in outputs)
                { 
                    Argument argument;
                    if (this.properties.TryGetValue(output.Key, out argument) && argument != null) 
                    { 
                        if (argument.Direction == ArgumentDirection.Out)
                        { 
                            argument.Set(context, output.Value);
                        }
                    }
                } 
            }
        } 
 
        internal IDictionary GetInputArgumentValues(NativeActivityContext context)
        { 
            Dictionary arguments = null;

            if (this.properties != null)
            { 
                foreach (KeyValuePair parameter in this.properties)
                { 
                    Argument argument = parameter.Value; 

                    if (argument.Direction == ArgumentDirection.In) 
                    {
                        if (arguments == null)
                        {
                            arguments = new Dictionary(); 
                        }
 
                        arguments.Add(parameter.Key, argument.Get(context)); 
                    }
                } 
            }

            return arguments;
        } 

        System.Workflow.ComponentModel.Activity CreateActivity() 
        { 
            Debug.Assert(this.ActivityType != null, "ActivityType must be set by the time we get here");
 
            System.Workflow.ComponentModel.Activity activity = Activator.CreateInstance(this.ActivityType) as System.Workflow.ComponentModel.Activity;
            Debug.Assert(activity != null, "We should have validated that the type has a default ctor() and derives from System.Workflow.ComponentModel.Activity.");

            return activity; 
        }
 
        void InitializeMetaProperties(System.Workflow.ComponentModel.Activity activity) 
        {
            Debug.Assert((activity.GetType() == this.ActivityType), "activity must be the same type as this.ActivityType"); 
            if (this.metaProperties != null && this.metaProperties.Count > 0)
            {
                foreach (string name in this.metaProperties.Keys)
                { 
                    PropertyInfo property = this.ActivityType.GetProperty(name);
                    if (property == null) 
                    { 
                        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.MetaPropertyDoesNotExist, name, this.ActivityType.FullName));
                    } 
                    property.SetValue(activity, this.metaProperties[name], null);
                }
            }
        } 

        void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object state) 
        { 
            InteropExecutor interopExecutor = this.interopActivityExecutor.Get(context);
 
            if (!interopExecutor.HasCheckedForTrackingParticipant)
            {
                interopExecutor.TrackingEnabled = (context.GetExtension() != null);
                interopExecutor.HasCheckedForTrackingParticipant = true; 
            }
 
            interopExecutor.EnsureReload(this); 

            try 
            {
                using (InteropEnvironment interopEnvironment = new InteropEnvironment(
                    interopExecutor, context,
                    this.onResumeBookmark, 
                    this,
                    this.runtimeTransactionHandle.Get(context).GetCurrentTransaction(context))) 
                { 
                    IComparable queueName = interopExecutor.BookmarkQueueMap[bookmark];
                    interopEnvironment.EnqueueEvent(queueName, state); 
                }
            }
            catch (Exception exception)
            { 
                if (WorkflowExecutor.IsIrrecoverableException(exception) || !this.persistOnClose.Get(context))
                { 
                    throw; 
                }
 
                // We are not ----ing the exception.  The exception is saved in this.outstandingException.
                // We will throw the exception from OnPersistComplete.
            }
        } 

        AttributeCollection ICustomTypeDescriptor.GetAttributes() 
        { 
            return TypeDescriptor.GetAttributes(this, true);
        } 

        string ICustomTypeDescriptor.GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true); 
        }
 
        string ICustomTypeDescriptor.GetComponentName() 
        {
            return TypeDescriptor.GetComponentName(this, true); 
        }

        TypeConverter ICustomTypeDescriptor.GetConverter()
        { 
            return TypeDescriptor.GetConverter(this, true);
        } 
 
        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        { 
            return TypeDescriptor.GetDefaultEvent(this, true);
        }

        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() 
        {
            return TypeDescriptor.GetDefaultProperty(this, true); 
        } 

        object ICustomTypeDescriptor.GetEditor(Type editorBaseType) 
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, true);
        }
 
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        { 
            return TypeDescriptor.GetEvents(this, attributes, true); 
        }
 
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return TypeDescriptor.GetEvents(this, true);
        } 

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) 
        { 
            List properties = new List();
 
            PropertyDescriptorCollection interopProperties;
            if (attributes != null)
            {
                interopProperties = TypeDescriptor.GetProperties(this, attributes, true); 
            }
            else 
            { 
                interopProperties = TypeDescriptor.GetProperties(this, true);
            } 
            for (int i = 0; i < interopProperties.Count; i++)
            {
                properties.Add(interopProperties[i]);
            } 

            if (this.hasValidBody) 
            { 
                // First, cache the full set of body properties
                if (!this.exposedBodyPropertiesCacheIsValid) 
                {
                    //Create matched pair of RuntimeArguments for every property: Property (InArgument) & PropertyOut (Argument)
                    PropertyInfo[] bodyProperties = this.ActivityType.GetProperties();
                    // recheck for name collisions 
                    this.hasNameCollision = InteropEnvironment.ParameterHelper.HasPropertyNameCollision(bodyProperties);
                    for (int i = 0; i < bodyProperties.Length; i++) 
                    { 
                        PropertyInfo property = bodyProperties[i];
                        bool isMetaProperty; 
                        if (InteropEnvironment.ParameterHelper.IsBindableOrMetaProperty(property, out isMetaProperty))
                        {
                            // Propagate the attributes to the PropertyDescriptor, appending a DesignerSerializationVisibility attribute
                            Attribute[] customAttributes = Attribute.GetCustomAttributes(property, true); 
                            Attribute[] newAttributes = new Attribute[customAttributes.Length + 1];
                            customAttributes.CopyTo(newAttributes, 0); 
                            newAttributes[customAttributes.Length] = new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden); 

                            if (this.exposedBodyProperties == null) 
                            {
                                this.exposedBodyProperties = new List(bodyProperties.Length);
                            }
                            if (isMetaProperty) 
                            {
                                InteropProperty descriptor = new LiteralProperty(this, property.Name, property.PropertyType, newAttributes); 
                                this.exposedBodyProperties.Add(descriptor); 
                            }
                            else 
                            {
                                InteropProperty inDescriptor;
                                //If there are any Property/PropertyOut name pairs already extant, we fall back to renaming the InArgument half of the pair as well
                                if (this.hasNameCollision) 
                                {
                                    inDescriptor = new ArgumentProperty(this, property.Name + InArgumentSuffix, Argument.Create(property.PropertyType, ArgumentDirection.In), newAttributes); 
                                } 
                                else
                                { 
                                    inDescriptor = new ArgumentProperty(this, property.Name, Argument.Create(property.PropertyType, ArgumentDirection.In), newAttributes);
                                }
                                this.exposedBodyProperties.Add(inDescriptor);
                                //We always rename the OutArgument half of the pair 
                                InteropProperty outDescriptor = new ArgumentProperty(this, property.Name + OutArgumentSuffix, Argument.Create(property.PropertyType, ArgumentDirection.Out), newAttributes);
                                this.exposedBodyProperties.Add(outDescriptor); 
                            } 
                        }
                    } 
                    this.exposedBodyPropertiesCacheIsValid = true;
                }
                // Now adds body properties, complying with the filter:
                if (this.exposedBodyProperties != null) 
                {
                    for (int i = 0; i < this.exposedBodyProperties.Count; i++) 
                    { 
                        PropertyDescriptor descriptor = this.exposedBodyProperties[i];
                        if (attributes == null || !ShouldFilterProperty(descriptor, attributes)) 
                        {
                            properties.Add(descriptor);
                        }
                    } 
                }
            } 
 
            return new PropertyDescriptorCollection(properties.ToArray());
        } 

        static bool ShouldFilterProperty(PropertyDescriptor property, Attribute[] attributes)
        {
            if (attributes == null || attributes.Length == 0) 
            {
                return false; 
            } 

            for (int i = 0; i < attributes.Length; i++) 
            {
                Attribute filterAttribute = attributes[i];
                Attribute propertyAttribute = property.Attributes[filterAttribute.GetType()];
                if (propertyAttribute == null) 
                {
                    if (!filterAttribute.IsDefaultAttribute()) 
                    { 
                        return true;
                    } 
                }
                else
                {
                    if (!filterAttribute.Match(propertyAttribute)) 
                    {
                        return true; 
                    } 
                }
            } 
            return false;
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() 
        {
            return ((ICustomTypeDescriptor)this).GetProperties(null); 
        } 

        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) 
        {
            InteropProperty intProp = pd as InteropProperty;
            if (intProp != null)
            { 
                return intProp.Owner;
            } 
            else 
            {
                return this; 
            }
        }

        internal void OnClose(NativeActivityContext context, Exception exception) 
        {
            if (this.persistOnClose.Get(context)) 
            { 
                if (exception == null)
                { 
                    context.ScheduleActivity(this.persistActivity);
                }
                else
                { 
                    // The V1 workflow faulted and there is an uncaught exception. We cannot throw
                    // the exception right away because we must Persist in order to process the WorkBatch. 
                    // So we are saving the uncaught exception and scheduling the Persist activity with a completion callback. 
                    // We will throw the exception from OnPersistComplete.
                    this.outstandingException.Set(context, exception); 

                    if (this.onPersistComplete == null)
                    {
                        this.onPersistComplete = new CompletionCallback(this.OnPersistComplete); 
                    }
 
                    context.ScheduleActivity(this.persistActivity, this.onPersistComplete); 
                }
            } 

            this.interopEnlistment.Set(context, null);
        }
 
        internal void Persist(NativeActivityContext context)
        { 
            if (this.onPersistComplete == null) 
            {
                this.onPersistComplete = new CompletionCallback(this.OnPersistComplete); 
            }

            // If Persist fails for any reason, the workflow aborts
            context.ScheduleActivity(this.persistActivity, this.onPersistComplete); 
        }
 
        internal void OnPersistComplete(NativeActivityContext context, ActivityInstance completedInstance) 
        {
            this.persistOnClose.Set(context, false); 
            Exception exception = this.outstandingException.Get(context);
            if (exception != null)
            {
                this.outstandingException.Set(context, null); 
                throw exception;
            } 
 
            this.Resume(context, null);
        } 

        internal void CreateTransaction(NativeActivityContext context, TransactionOptions txOptions)
        {
            RuntimeTransactionHandle transactionHandle = this.runtimeTransactionHandle.Get(context); 
            Debug.Assert(transactionHandle != null, "RuntimeTransactionHandle is null");
 
            transactionHandle.RequestTransactionContext(context, OnTransactionContextAcquired, txOptions); 
        }
 
        void OnTransactionContextAcquired(NativeActivityTransactionContext context, object state)
        {
            Debug.Assert(context != null, "ActivityTransactionContext was null");
            TransactionOptions txOptions = (TransactionOptions)state; 
            CommittableTransaction transaction = new CommittableTransaction(txOptions);
            context.SetRuntimeTransaction(transaction); 
            this.Resume(context, transaction); 
        }
 
        internal void CommitTransaction(NativeActivityContext context)
        {
            if (this.onTransactionComplete == null)
            { 
                this.onTransactionComplete = new BookmarkCallback(this.OnTransactionComplete);
            } 
 
            RuntimeTransactionHandle transactionHandle = this.runtimeTransactionHandle.Get(context);
            transactionHandle.CompleteTransaction(context, this.onTransactionComplete); 
        }

        void OnTransactionComplete(NativeActivityContext context, Bookmark bookmark, object state)
        { 
            this.Resume(context, null);
        } 
 
        void Resume(NativeActivityContext context, Transaction transaction)
        { 
            InteropExecutor interopExecutor = this.interopActivityExecutor.Get(context);

            if (!interopExecutor.HasCheckedForTrackingParticipant)
            { 
                interopExecutor.TrackingEnabled = (context.GetExtension() != null);
                interopExecutor.HasCheckedForTrackingParticipant = true; 
            } 

            interopExecutor.EnsureReload(this); 

            try
            {
                using (InteropEnvironment interopEnvironment = new InteropEnvironment( 
                    interopExecutor, context,
                    this.onResumeBookmark, 
                    this, 
                    transaction))
                { 
                    interopEnvironment.Resume();
                }
            }
            catch (Exception exception) 
            {
                if (WorkflowExecutor.IsIrrecoverableException(exception) || !this.persistOnClose.Get(context)) 
                { 
                    throw;
                } 

                // We are not ----ing the exception.  The exception is saved in this.outstandingException.
                // We will throw the exception from OnPersistComplete.
            } 
        }
 
        internal void AddResourceManager(NativeActivityContext context, VolatileResourceManager resourceManager) 
        {
            if (Transaction.Current != null && 
                Transaction.Current.TransactionInformation.Status == TransactionStatus.Active)
            {
                InteropEnlistment enlistment = this.interopEnlistment.Get(context);
                if (enlistment == null || !enlistment.IsValid) 
                {
                    enlistment = new InteropEnlistment(Transaction.Current, resourceManager); 
                    Transaction.Current.EnlistVolatile(enlistment, EnlistmentOptions.EnlistDuringPrepareRequired); 
                    this.interopEnlistment.Set(context, enlistment);
                } 
            }
            else
            {
                InteropPersistenceParticipant persistenceParticipant = context.GetExtension(); 
                persistenceParticipant.Add(this.Id, resourceManager);
                this.persistOnClose.Set(context, true); 
            } 
        }
 
        Constraint ProcessAdvancedConstraints()
        {
            DelegateInArgument element = new DelegateInArgument() { Name = "element" };
            DelegateInArgument validationContext = new DelegateInArgument() { Name = "validationContext" }; 
            DelegateInArgument parent = new DelegateInArgument() { Name = "parent" };
 
            //This will accumulate all potential violations at the root level. See the use case DIRECT of the Interop spec 
            Variable> rootValidationDataVar = new Variable>(context => new HashSet());
 
            //This will accumulate all violations at the nested level. See the use case NESTED of the Interop spec
            Variable> nestedChildrenValidationDataVar = new Variable>(context => new HashSet());

            return new Constraint 
            {
                Body = new ActivityAction 
                { 
                    Argument1 = element,
                    Argument2 = validationContext, 
                    Handler = new If
                    {
                        Condition = new InArgument(env => element.Get(env).hasValidBody),
                        Then = new Sequence 
                        {
                             Variables = { rootValidationDataVar, nestedChildrenValidationDataVar }, 
                             Activities = 
                             {
                                //First traverse the interop body and collect all available data for validation. This is done at all levels, DIRECT and NESTED 
                                new WalkInteropBodyAndGatherData()
                                {
                                     RootLevelValidationData = new InArgument>(rootValidationDataVar),
                                     NestedChildrenValidationData = new InArgument>(nestedChildrenValidationDataVar), 
                                     InteropActivity = element
                                }, 
                                //This is based off the table in the Interop spec. 
                                new ValidateAtRootAndNestedLevels()
                                { 
                                     RootLevelValidationData = rootValidationDataVar,
                                     NestedChildrenValidationData = nestedChildrenValidationDataVar,
                                     Interop = element,
                                }, 
                                //Traverse the parent chain of the Interop activity to look for specifc violations regarding composition of 3.0 activities within 4.0 activities.
                                //Specifically, 
                                //  - 3.0 TransactionScope within a 4.0 TransactionScope 
                                //  - 3.0 PersistOnClose within a 4.0 TransactionScope
                                // 
                                new ForEach
                                {
                                    Values = new GetParentChain
                                    { 
                                        ValidationContext = validationContext,
                                    }, 
                                    Body = new ActivityAction 
                                    {
                                        Argument = parent, 
                                        Handler = new Sequence
                                        {
                                            Activities =
                                            { 
                                                new If()
                                                { 
                                                    Condition = new Or 
                                                    {
                                                        Left = new Equal 
                                                        {
                                                            Left = new ObtainType
                                                            {
                                                                Input = parent, 
                                                            },
                                                            Right = new InArgument(context => typeof(System.Activities.Statements.TransactionScope)) 
                                                        }, 
                                                        Right = new Equal
                                                        { 
                                                            Left = new InArgument(env => parent.Get(env).GetType().FullName),
                                                            Right = "System.ServiceModel.Activities.TransactedReceiveScope"
                                                        }
                                                    }, 
                                                    Then = new Sequence
                                                    { 
                                                        Activities = 
                                                        {
                                                            new AssertValidation 
                                                            {
                                                                //Here we only pass the NestedChildrenValidationData since root level use
                                                                //of TransactionScope would have already been flagged as an error
                                                                Assertion = new CheckForTransactionScope() 
                                                                {
                                                                     ValidationResults = nestedChildrenValidationDataVar 
                                                                }, 
                                                                Message = new InArgument(ExecutionStringManager.InteropBodyNestedTransactionScope)
                                                            }, 
                                                            new AssertValidation
                                                            {
                                                                Assertion = new CheckForPersistOnClose()
                                                                { 
                                                                     NestedChildrenValidationData = nestedChildrenValidationDataVar,
                                                                     RootLevelValidationData = rootValidationDataVar 
                                                                }, 
                                                                Message = new InArgument(ExecutionStringManager.InteropBodyNestedPersistOnCloseWithinTransactionScope)
                                                            }, 

                                                        }
                                                    },
                                                }, 
                                            }
                                        } 
                                    } 
                                },
                                new ActivityTreeValidation() 
                                {
                                    Interop = element
                                }
                            } 
                        }
                    } 
                } 
            };
        } 

        class ActivityTreeValidation : NativeActivity
        {
            public ActivityTreeValidation() 
            {
            } 
 
            public InArgument Interop
            { 
                get;
                set;
            }
 
            protected override void Execute(NativeActivityContext context)
            { 
                Interop interop = this.Interop.Get(context); 

                if (interop == null) 
                {
                    return;
                }
 
                if (!typeof(System.Workflow.ComponentModel.Activity).IsAssignableFrom(interop.ActivityType))
                { 
                    return; 
                }
 
                System.ComponentModel.Design.ServiceContainer container = new System.ComponentModel.Design.ServiceContainer();
                container.AddService(typeof(ITypeProvider), CreateTypeProvider(interop.ActivityType));
                ValidationManager manager = new ValidationManager(container);
 
                System.Workflow.ComponentModel.Activity interopBody = interop.ComponentModelActivity;
                using (WorkflowCompilationContext.CreateScope(manager)) 
                { 
                    foreach (Validator validator in manager.GetValidators(interop.ActivityType))
                    { 
                        ValidationErrorCollection errors = validator.Validate(manager, interopBody);
                        foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in errors)
                        {
                            Constraint.AddValidationError(context, new ValidationError(error.ErrorText, error.IsWarning, error.PropertyName)); 
                        }
                    } 
                } 
            }
 
            static TypeProvider CreateTypeProvider(Type rootType)
            {
                TypeProvider typeProvider = new TypeProvider(null);
 
                typeProvider.SetLocalAssembly(rootType.Assembly);
                typeProvider.AddAssembly(rootType.Assembly); 
 
                foreach (AssemblyName assemblyName in rootType.Assembly.GetReferencedAssemblies())
                { 
                    Assembly referencedAssembly = null;
                    try
                    {
                        referencedAssembly = Assembly.Load(assemblyName); 
                        if (referencedAssembly != null)
                            typeProvider.AddAssembly(referencedAssembly); 
                    } 
                    catch
                    { 
                    }

                    if (referencedAssembly == null && assemblyName.CodeBase != null)
                        typeProvider.AddAssemblyReference(assemblyName.CodeBase); 
                }
 
                return typeProvider; 
            }
        } 

        class CheckForTransactionScope : CodeActivity
        {
            public InArgument> ValidationResults 
            {
                get; 
                set; 
            }
 
            protected override bool Execute(CodeActivityContext context)
            {
                HashSet validationResults = this.ValidationResults.Get(context);
                if (validationResults.Contains(InteropValidationEnum.TransactionScope)) 
                {
                    return false; 
                } 

                return true; 
            }
        }

        class CheckForPersistOnClose : CodeActivity 
        {
            public InArgument> NestedChildrenValidationData 
            { 
                get;
                set; 
            }

            public InArgument> RootLevelValidationData
            { 
                get;
                set; 
            } 

            protected override bool Execute(CodeActivityContext context) 
            {
                HashSet nestedValidationData = this.NestedChildrenValidationData.Get(context);
                HashSet rootValidationData = this.RootLevelValidationData.Get(context);
 
                if (nestedValidationData.Contains(InteropValidationEnum.PersistOnClose) || rootValidationData.Contains(InteropValidationEnum.PersistOnClose))
                { 
                    return false; 
                }
 
                return true;
            }
        }
 
        class ValidateAtRootAndNestedLevels : NativeActivity
        { 
            public ValidateAtRootAndNestedLevels() 
            {
            } 

            public InArgument Interop
            {
                get; 
                set;
            } 
 
            public InArgument> RootLevelValidationData
            { 
                get;
                set;
            }
 
            public InArgument> NestedChildrenValidationData
            { 
                get; 
                set;
            } 

            protected override void Execute(NativeActivityContext context)
            {
                Interop activity = this.Interop.Get(context); 

                foreach (InteropValidationEnum validationEnum in this.RootLevelValidationData.Get(context)) 
                { 
                    //We care to mark PersistOnClose during the walking algorithm because we need to check if it happens under a 4.0 TransactionScopActivity and flag that
                    //That is done later, so skip here. 
                    if (validationEnum != InteropValidationEnum.PersistOnClose)
                    {
                        string message = string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropBodyRootLevelViolation, activity.DisplayName, validationEnum.ToString() + "Activity");
                        Constraint.AddValidationError(context, new ValidationError(message)); 
                    }
                } 
 
                foreach (InteropValidationEnum validationEnum in this.NestedChildrenValidationData.Get(context))
                { 
                    //We care to mark PersistOnClose or TransactionScope during the walking algorithm because we need to check if it happens under a 4.0 TransactionScopActivity and flag that
                    //That is done later, so skip here.
                    if ((validationEnum != InteropValidationEnum.PersistOnClose) && (validationEnum != InteropValidationEnum.TransactionScope))
                    { 
                        string message = string.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InteropBodyNestedViolation, activity.DisplayName, validationEnum.ToString() + "Activity");
                        Constraint.AddValidationError(context, new ValidationError(message)); 
                    } 
                }
            } 
        }

        class WalkInteropBodyAndGatherData : System.Activities.CodeActivity
        { 
            public InArgument InteropActivity
            { 
                get; 
                set;
            } 

            public InArgument> RootLevelValidationData
            {
                get; 
                set;
            } 
 
            public InArgument> NestedChildrenValidationData
            { 
                get;
                set;
            }
 
            protected override void Execute(CodeActivityContext context)
            { 
                Interop interop = this.InteropActivity.Get(context); 
                Debug.Assert(interop != null, "Interop activity is null");
 
                Debug.Assert(interop.hasValidBody, "Interop activity has an invalid body");

                System.Workflow.ComponentModel.Activity interopBody = interop.ComponentModelActivity;
                Debug.Assert(interopBody != null, "Interop Body was null"); 

                HashSet validationResults; 
                validationResults = this.RootLevelValidationData.Get(context); 
                Debug.Assert(validationResults != null, "The RootLevelValidationData hash set was null");
 
                //Gather data at root level first
                ProcessAtRootLevel(interopBody, validationResults);

                validationResults = null; 
                validationResults = this.NestedChildrenValidationData.Get(context);
                Debug.Assert(validationResults != null, "The NestedChildrenValidationData hash set was null"); 
 
                //Next, process nested children of the Body
                if (interopBody is System.Workflow.ComponentModel.CompositeActivity) 
                {
                    ProcessNestedChildren(interopBody, validationResults);
                }
 
                return;
            } 
 
            void ProcessAtRootLevel(System.Workflow.ComponentModel.Activity interopBody, HashSet validationResults)
            { 
                Debug.Assert(interopBody != null, "Interop Body is null");
                Debug.Assert(validationResults != null, "The HashSet of validation results is null");

                if (interopBody.PersistOnClose) 
                {
                    validationResults.Add(InteropValidationEnum.PersistOnClose); 
                } 

                Type interopBodyType = interopBody.GetType(); 
                if (interopBodyType == typeof(System.Workflow.ComponentModel.TransactionScopeActivity))
                {
                    validationResults.Add(InteropValidationEnum.TransactionScope);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.CodeActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Code); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.DelayActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.Delay);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.InvokeWebServiceActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.InvokeWebService); 
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.InvokeWorkflowActivity))
                { 
                    validationResults.Add(InteropValidationEnum.InvokeWorkflow);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.PolicyActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Policy);
                } 
                else if (interopBodyType.FullName == "System.Workflow.Activities.SendActivity") 
                {
                    validationResults.Add(InteropValidationEnum.Send); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.SetStateActivity))
                {
                    validationResults.Add(InteropValidationEnum.SetState); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.WebServiceFaultActivity)) 
                { 
                    validationResults.Add(InteropValidationEnum.WebServiceFault);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.WebServiceInputActivity))
                {
                    validationResults.Add(InteropValidationEnum.WebServiceInput);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.WebServiceOutputActivity))
                { 
                    validationResults.Add(InteropValidationEnum.WebServiceOutput); 
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.CompensateActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.Compensate);
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.SuspendActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.Suspend); 
                } 
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.TerminateActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Terminate);
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.ThrowActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Throw);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.ConditionedActivityGroup)) 
                {
                    validationResults.Add(InteropValidationEnum.ConditionedActivityGroup); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.EventHandlersActivity))
                {
                    validationResults.Add(InteropValidationEnum.EventHandlers); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.EventHandlingScopeActivity)) 
                { 
                    validationResults.Add(InteropValidationEnum.EventHandlingScope);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.IfElseActivity))
                {
                    validationResults.Add(InteropValidationEnum.IfElse);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.ListenActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Listen); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.ParallelActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.Parallel);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.ReplicatorActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.Replicator); 
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.SequenceActivity))
                { 
                    validationResults.Add(InteropValidationEnum.Sequence);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.CompensatableSequenceActivity))
                { 
                    validationResults.Add(InteropValidationEnum.CompensatableSequence);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.EventDrivenActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.EventDriven); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.IfElseBranchActivity))
                {
                    validationResults.Add(InteropValidationEnum.IfElseBranch); 
                }
                else if (interopBodyType.FullName == "System.Workflow.Activities.ReceiveActivity") 
                { 
                    validationResults.Add(InteropValidationEnum.Receive);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.SequentialWorkflowActivity))
                {
                    validationResults.Add(InteropValidationEnum.SequentialWorkflow);
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.StateFinalizationActivity))
                { 
                    validationResults.Add(InteropValidationEnum.StateFinalization); 
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.StateInitializationActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.StateInitialization);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.StateActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.State); 
                } 
                else if (interopBodyType == typeof(System.Workflow.Activities.StateMachineWorkflowActivity))
                { 
                    validationResults.Add(InteropValidationEnum.StateMachineWorkflow);
                }
                else if (interopBodyType == typeof(System.Workflow.Activities.WhileActivity))
                { 
                    validationResults.Add(InteropValidationEnum.While);
                } 
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.CancellationHandlerActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.CancellationHandler); 
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.CompensatableTransactionScopeActivity))
                {
                    validationResults.Add(InteropValidationEnum.CompensatableTransactionScope); 
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.CompensationHandlerActivity)) 
                { 
                    validationResults.Add(InteropValidationEnum.CompensationHandler);
                } 
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.FaultHandlerActivity))
                {
                    validationResults.Add(InteropValidationEnum.FaultHandler);
                } 
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.FaultHandlersActivity))
                { 
                    validationResults.Add(InteropValidationEnum.FaultHandlers); 
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.SynchronizationScopeActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.SynchronizationScope);
                }
                else if (interopBodyType == typeof(System.Workflow.ComponentModel.ICompensatableActivity)) 
                {
                    validationResults.Add(InteropValidationEnum.ICompensatable); 
                } 
            }
 
            void ProcessNestedChildren(System.Workflow.ComponentModel.Activity interopBody, HashSet validationResults)
            {
                Debug.Assert(interopBody != null, "Interop Body is null");
                Debug.Assert(validationResults != null, "The HashSet of validation results is null"); 
                bool persistOnClose = false;
 
                foreach (System.Workflow.ComponentModel.Activity activity in interopBody.CollectNestedActivities()) 
                {
                    if (activity.PersistOnClose) 
                    {
                        persistOnClose = true;
                    }
 
                    if (activity is System.Workflow.ComponentModel.TransactionScopeActivity)
                    { 
                        validationResults.Add(InteropValidationEnum.TransactionScope); 
                    }
                    else if (activity is System.Workflow.Activities.InvokeWorkflowActivity) 
                    {
                        validationResults.Add(InteropValidationEnum.InvokeWorkflow);
                    }
                    // SendActivity is sealed 
                    else if (activity.GetType().FullName == "System.Workflow.Activities.SendActivity")
                    { 
                        validationResults.Add(InteropValidationEnum.Send); 
                    }
                    else if (activity is System.Workflow.Activities.WebServiceFaultActivity) 
                    {
                        validationResults.Add(InteropValidationEnum.WebServiceFault);
                    }
                    else if (activity is System.Workflow.Activities.WebServiceInputActivity) 
                    {
                        validationResults.Add(InteropValidationEnum.WebServiceInput); 
                    } 
                    else if (activity is System.Workflow.Activities.WebServiceOutputActivity)
                    { 
                        validationResults.Add(InteropValidationEnum.WebServiceOutput);
                    }
                    else if (activity is System.Workflow.ComponentModel.CompensateActivity)
                    { 
                        validationResults.Add(InteropValidationEnum.Compensate);
                    } 
                    else if (activity is System.Workflow.ComponentModel.SuspendActivity) 
                    {
                        validationResults.Add(InteropValidationEnum.Suspend); 
                    }
                    else if (activity is System.Workflow.Activities.CompensatableSequenceActivity)
                    {
                        validationResults.Add(InteropValidationEnum.CompensatableSequence); 
                    }
                    // ReceiveActivity is sealed 
                    else if (activity.GetType().FullName == "System.Workflow.Activities.ReceiveActivity") 
                    {
                        validationResults.Add(InteropValidationEnum.Receive); 
                    }
                    else if (activity is System.Workflow.ComponentModel.CompensatableTransactionScopeActivity)
                    {
                        validationResults.Add(InteropValidationEnum.CompensatableTransactionScope); 
                    }
                    else if (activity is System.Workflow.ComponentModel.CompensationHandlerActivity) 
                    { 
                        validationResults.Add(InteropValidationEnum.CompensationHandler);
                    } 
                    else if (activity is System.Workflow.ComponentModel.ICompensatableActivity)
                    {
                        validationResults.Add(InteropValidationEnum.ICompensatable);
                    } 
                }
 
                if (persistOnClose) 
                {
                    validationResults.Add(InteropValidationEnum.PersistOnClose); 
                }
            }
        }
 
        //This needs to be in [....] with the table in the spec
        //We use this internally to keep a hashset of validation data 
        enum InteropValidationEnum 
        {
            Code, 
            Delay,
            InvokeWebService,
            InvokeWorkflow,
            Policy, 
            Send,
            SetState, 
            WebServiceFault, 
            WebServiceInput,
            WebServiceOutput, 
            Compensate,
            Suspend,
            ConditionedActivityGroup,
            EventHandlers, 
            EventHandlingScope,
            IfElse, 
            Listen, 
            Parallel,
            Replicator, 
            Sequence,
            CompensatableSequence,
            EventDriven,
            IfElseBranch, 
            Receive,
            SequentialWorkflow, 
            StateFinalization, 
            StateInitialization,
            State, 
            StateMachineWorkflow,
            While,
            CancellationHandler,
            CompensatableTransactionScope, 
            CompensationHandler,
            FaultHandler, 
            FaultHandlers, 
            SynchronizationScope,
            TransactionScope, 
            ICompensatable,
            PersistOnClose,
            Terminate,
            Throw 
        }
 
        class ObtainType : CodeActivity 
        {
            public ObtainType() 
            {
            }

            public InArgument Input 
            {
                get; 
                set; 
            }
 
            protected override Type Execute(CodeActivityContext context)
            {
                return this.Input.Get(context).GetType();
            } 
        }
 
        abstract class InteropProperty : PropertyDescriptor 
        {
            Interop owner; 
            bool isValid;

            public InteropProperty(Interop owner, string name, Attribute[] propertyInfoAttributes)
                : base(name, propertyInfoAttributes) 
            {
                this.owner = owner; 
                this.isValid = true; 
            }
 
            public override Type ComponentType
            {
                get
                { 
                    ThrowIfInvalid();
                    return this.owner.GetType(); 
                } 
            }
 
            protected internal Interop Owner
            {
                get
                { 
                    return this.owner;
                } 
            } 

            public override bool CanResetValue(object component) 
            {
                ThrowIfInvalid();
                return false;
            } 

            public override void ResetValue(object component) 
            { 
                ThrowIfInvalid();
            } 

            public override bool ShouldSerializeValue(object component)
            {
                ThrowIfInvalid(); 
                return false;
            } 
 
            protected void ThrowIfInvalid()
            { 
                if (!this.isValid)
                {
                    throw new InvalidOperationException(ExecutionStringManager.InteropInvalidPropertyDescriptor);
                } 
            }
 
            internal void Invalidate() 
            {
                this.isValid = false; 
            }
        }

        class ArgumentProperty : InteropProperty 
        {
            string argumentName; 
            Argument argument; 

            public ArgumentProperty(Interop owner, string argumentName, Argument argument, Attribute[] attributes) 
                : base(owner, argumentName, attributes)
            {
                this.argumentName = argumentName;
                this.argument = argument; 
            }
 
            public override bool IsReadOnly 
            {
                get 
                {
                    ThrowIfInvalid();
                    return false;
                } 
            }
 
            public override Type PropertyType 
            {
                get 
                {
                    ThrowIfInvalid();
                    return GetArgument().GetType();
                } 
            }
 
            public override object GetValue(object component) 
            {
                ThrowIfInvalid(); 
                return GetArgument();
            }

            public override void SetValue(object component, object value) 
            {
                ThrowIfInvalid(); 
                if (value != null) 
                {
                    this.Owner.ActivityProperties[this.argumentName] = (Argument)value; 
                }
                else
                {
                    this.Owner.ActivityProperties.Remove(this.argumentName); 
                }
            } 
 
            Argument GetArgument()
            { 
                Argument argument;
                if (!this.Owner.ActivityProperties.TryGetValue(this.argumentName, out argument))
                {
                    argument = this.argument; 
                }
                return argument; 
            } 
        }
 
        class LiteralProperty : InteropProperty
        {
            string literalName;
            Type literalType; 

            public LiteralProperty(Interop owner, string literalName, Type literalType, Attribute[] attributes) 
                : base(owner, literalName, attributes) 
            {
                this.literalName = literalName; 
                this.literalType = literalType;
            }

            public override bool IsReadOnly 
            {
                get 
                { 
                    ThrowIfInvalid();
                    return false; 
                }
            }

            public override Type PropertyType 
            {
                get 
                { 
                    ThrowIfInvalid();
                    return this.literalType; 
                }
            }

            public override object GetValue(object component) 
            {
                ThrowIfInvalid(); 
                return GetLiteral(); 
            }
 
            public override void SetValue(object component, object value)
            {
                ThrowIfInvalid();
                this.Owner.ActivityMetaProperties[this.literalName] = value; 
            }
 
            object GetLiteral() 
            {
                object literal; 
                if (this.Owner.ActivityMetaProperties.TryGetValue(this.literalName, out literal))
                {
                    return literal;
                } 
                else
                { 
                    return null; 
                }
            } 
        }

        class InteropPersistenceParticipant : PersistenceIOParticipant
        { 
            public InteropPersistenceParticipant()
                : base(true, false) 
            { 
                this.ResourceManagers = new Dictionary();
                this.CommittedResourceManagers = new Dictionary>(); 
            }

            Dictionary ResourceManagers
            { 
                get;
                set; 
            } 

            Dictionary> CommittedResourceManagers 
            {
                get;
                set;
            } 

            protected override IAsyncResult BeginOnSave(IDictionary readWriteValues, IDictionary writeOnlyValues, TimeSpan timeout, AsyncCallback callback, object state) 
            { 
                try
                { 
                    foreach (VolatileResourceManager rm in this.ResourceManagers.Values)
                    {
                        rm.Commit();
                    } 
                }
                finally 
                { 
                    this.CommittedResourceManagers.Add(Transaction.Current, this.ResourceManagers);
                    this.ResourceManagers = new Dictionary(); 
                    Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(Current_TransactionCompleted);
                }

                return new CompletedAsyncResult(callback, state); 
            }
 
            protected override void EndOnSave(IAsyncResult result) 
            {
                CompletedAsyncResult.End(result); 
            }

            void Current_TransactionCompleted(object sender, TransactionEventArgs e)
            { 
                if (e.Transaction.TransactionInformation.Status == TransactionStatus.Committed)
                { 
                    foreach (VolatileResourceManager rm in this.CommittedResourceManagers[e.Transaction].Values) 
                    {
                        rm.Complete(); 
                    }
                }
                else
                { 
                    foreach (VolatileResourceManager rm in this.CommittedResourceManagers[e.Transaction].Values)
                    { 
                        rm.ClearAllBatchedWork(); 
                    }
                } 
                this.CommittedResourceManagers.Remove(e.Transaction);
            }

            protected override void Abort() 
            {
                foreach (VolatileResourceManager rm in this.ResourceManagers.Values) 
                { 
                    rm.ClearAllBatchedWork();
                } 

                this.ResourceManagers = new Dictionary();
            }
 
            internal void Add(string activityId, VolatileResourceManager rm)
            { 
                // Add and OnSave shouldn't be called at the same time.  A lock isn't needed here. 
                this.ResourceManagers.Add(activityId, rm);
            } 
        }

        [DataContract]
        class InteropEnlistment : IEnlistmentNotification 
        {
            VolatileResourceManager resourceManager; 
            Transaction transaction; 

            public InteropEnlistment() 
            {
            }

            public InteropEnlistment(Transaction transaction, VolatileResourceManager resourceManager) 
            {
                this.resourceManager = resourceManager; 
                this.transaction = transaction; 
                this.IsValid = true;
            } 

            public bool IsValid { get; set; }

            public void Commit(Enlistment enlistment) 
            {
                this.resourceManager.Complete(); 
                enlistment.Done(); 
            }
 
            public void InDoubt(Enlistment enlistment)
            {
                // Following the WF3 runtime behavior - Aborting during InDoubt
                this.Rollback(enlistment); 
            }
 
            public void Prepare(PreparingEnlistment preparingEnlistment) 
            {
                using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope(this.transaction)) 
                {
                    this.resourceManager.Commit();
                    ts.Complete();
                } 
                preparingEnlistment.Prepared();
            } 
 
            public void Rollback(Enlistment enlistment)
            { 
                this.resourceManager.ClearAllBatchedWork();
                enlistment.Done();
            }
        } 

        class CompletedAsyncResult : IAsyncResult 
        { 
            AsyncCallback callback;
            bool endCalled; 
            ManualResetEvent manualResetEvent;
            object state;
            object thisLock;
 
            public CompletedAsyncResult(AsyncCallback callback, object state)
            { 
                this.callback = callback; 
                this.state = state;
                this.thisLock = new object(); 

                if (callback != null)
                {
                    try 
                    {
                        callback(this); 
                    } 
                    catch (Exception e) // transfer to another thread, this is a fatal situation
                    { 
                        throw new InvalidProgramException(ExecutionStringManager.AsyncCallbackThrewException, e);
                    }
                }
            } 

            public static void End(IAsyncResult result) 
            { 
                if (result == null)
                { 
                    throw new ArgumentNullException("result");
                }

                CompletedAsyncResult asyncResult = result as CompletedAsyncResult; 

                if (asyncResult == null) 
                { 
                    throw new ArgumentException(ExecutionStringManager.InvalidAsyncResult, "result");
                } 

                if (asyncResult.endCalled)
                {
                    throw new InvalidOperationException(ExecutionStringManager.EndCalledTwice); 
                }
 
                asyncResult.endCalled = true; 

                if (asyncResult.manualResetEvent != null) 
                {
                    asyncResult.manualResetEvent.Close();
                }
            } 

            public object AsyncState 
            { 
                get
                { 
                    return state;
                }
            }
 
            public WaitHandle AsyncWaitHandle
            { 
                get 
                {
                    if (this.manualResetEvent != null) 
                    {
                        return this.manualResetEvent;
                    }
 
                    lock (ThisLock)
                    { 
                        if (this.manualResetEvent == null) 
                        {
                            this.manualResetEvent = new ManualResetEvent(true); 
                        }
                    }

                    return this.manualResetEvent; 
                }
            } 
 
            public bool CompletedSynchronously
            { 
                get
                {
                    return true;
                } 
            }
 
            public bool IsCompleted 
            {
                get 
                {
                    return true;
                }
            } 

            object ThisLock 
            { 
                get
                { 
                    return this.thisLock;
                }
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

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