locked
Activity can not access it's own variables RRS feed

  • Question

  • Hi,

    I have a Workflow Service with CreationEndpoint and want to pass arguments to the workfow instance. For this purpose I created an activity that takes an InArgument and proviedes it as a variable. Find the code below. The problem is, then I try to assign the InArgument's value to the variable I get an exception, telling me I can't do that:

    Exception: Activity '1: SequenceWithArguments' cannot access this variable because it is declared at the scope of activity '1: SequenceWithArguments'.  An activity can only access its own implementation variables.

    Basically the exception is telling me that the Activity can not access it's own variables. Is that a bug or do I do something wrong?

    namespace MSMQServiceAutoStartTestComposition.MSMQServiceWithCreationEndpoint
    {
      using System.Activities;
      using System.Collections.ObjectModel;
      using System.ComponentModel;
      using System.Linq;
      using System.Linq.Expressions;
    
      using MSMQServiceAutoStartTestComposition.Common;
    
      /// <summary>
      /// Provides an activity that is similar to the basic sequence activity. It is used to get workflow
      /// arguments into the workflow service if using a CreationEndpoint.
      /// </summary>
      [Designer(typeof(SequenceWithArgumentsDesigner))]
      public class SequenceWithArguments : NativeActivity
      {
        #region Fields
    
        /// <summary>
        /// All In-, InOut- and Out arguments of this activity.
        /// </summary>
        private Collection<RuntimeArgument> _arguments;
    
        /// <summary>
        /// This is a collection of all contained activities of this activity. 
        /// </summary>
        private Collection<Activity> _children;
    
        /// <summary>
        /// A collection of all variables defined within the scope of this activity.
        /// </summary>
        private Collection<Variable> _variables = new Collection<Variable>();
    
        /// <summary>
        /// Is used to determine if all child activities have been executed. Provides the index of the 
        /// current executed child activity.
        /// </summary>
        private Variable<int> _currentIndex;
    
        /// <summary>
        /// Indicates if the execution of a child activity is completed.
        /// </summary>
        private CompletionCallback _onChildComplete;
    
        #endregion Fields
    
        #region Constructor
    
        /// <summary>
        /// Initializes a new instance of the ExtendedSequenceActivity class. 
        /// It initializes the collections of variables, children, arguments.
        /// </summary>
        public SequenceWithArguments()
          : base()
        {
          _children = new Collection<Activity>();
          _variables = new Collection<Variable>();
          _arguments = new Collection<RuntimeArgument>();
          _currentIndex = new Variable<int>();
        }
    
        #endregion Constructor
    
        #region Arguments
    
        /// <summary>
        /// Gets or sets the job data within an object that is required to start the workflow instance.
        /// </summary>
        [Category("InArguments")]
        public InArgument<StartMessage> StartMessage { get; set; }
    
        /// <summary>
        /// Gets or sets the job data within an object that is required to start the workflow instance.
        /// </summary>
        [Category("OutArguments")]
        public OutArgument<StartMessage> ReceivedStartMessage { get; set; }
    
        #endregion Arguments
    
        #region Properties
    
        /// <summary>
        /// Gets the collection of child activities contained in this activity.
        /// </summary>
        public Collection<Activity> Activities
        {
          get
          {
            return _children;
          }
        }
    
        /// <summary>
        /// Gets the collection of variables defined within the scope of this activity.
        /// </summary>
        public Collection<Variable> Variables
        {
          get
          {
            return _variables;
          }
        }
    
        /// <summary>
        /// Gets a collection of all In-, InOut- and Out arguments of this activity.
        /// </summary>
        public Collection<RuntimeArgument> Arguments
        {
          get
          {
            return _arguments;
          }
        }
    
        #endregion Properties
    
        #region Methods
    
        /// <summary>
        /// Creates and validates a description of the activity’s arguments, variables,
        /// child activities, and activity delegates.
        /// </summary>
        /// <param name="metadata">The activity’s metadata that encapsulates the activity’s arguments, 
        /// variables, child activities, and activity delegates.
        /// </param>
        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
          base.CacheMetadata(metadata);
    
          metadata.AddImplementationVariable(_currentIndex);
        }
    
        /// <summary>
        /// Runs the activity’s execution logic. Checks for a break point.
        /// </summary>
        /// <param name="context">Provides the environmental execution context for the activity.</param>
        protected override void Execute(NativeActivityContext context)
        {
          ProvideJobData(context);
          InternalExecute(context, null);
        }
    
        /// <summary>
        /// Adds the received job data to execution properties of the activity context to make this 
        /// available in the whole workflow.
        /// </summary>
        /// <param name="context">The environmental execution context for the activity.</param>
        private void ProvideJobData(NativeActivityContext context)
        {
          RetriveWorkflowData(context);
        }
    
        /// <summary>
        /// Retrives the workflow data.
        /// </summary>
        /// <param name="context">The environmental execution context for the activity.</param>
        private void RetriveWorkflowData(NativeActivityContext context)
        {
          var jobData = this.StartMessage.Get(context);
          context.Properties.Add("data", jobData);
    
    
          SetStartMessageVariable(context, jobData);
    
          ReceivedStartMessage.Set(context, jobData);
        }
    
        /// <summary>
        /// Sets the start message variable.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="jobData">The job data.</param>
        private void SetStartMessageVariable(NativeActivityContext context, StartMessage jobData)
        {
          bool variableSet = false;
    
          foreach (var variable in this._variables)
          {
            if (variable.Name.ToLower() == "data")
            {
              variable.Set(context, jobData);
              variableSet = true;
              break;
            }
          }
    
          if (variableSet == false)
          {
            var variable = new Variable<StartMessage>();
            variable.Set(context, jobData);
            variable.Name = "data";
    
            this._variables.Add(variable);
          }
        }
    
        /// <summary>
        /// Executes the activity which means that all child activities are scheduled and executed.
        /// It is also used as CallBack method if a child activity completes.
        /// </summary>
        /// <param name="context">Provides the environmental execution context for the activity.</param>
        /// <param name="instance">The instance of the activity that has been completed.</param>
        private void InternalExecute(NativeActivityContext context, ActivityInstance instance)
        {
          // grab the index of the current activity
          var currentActivityIndex = _currentIndex.Get(context);
    
          if (currentActivityIndex == Activities.Count)
          {
            // if the currentActivityIndex is equal to the count of MySequence's Activities
            // MySequence is complete
            return;
          }
    
          if (_onChildComplete == null)
          {
            // on completion of the current child, have the runtime call back on this method
            _onChildComplete = new CompletionCallback(InternalExecute);
          }
    
          // grab the next Activity in MySequence.Activities and schedule it
          Activity nextChild = Activities[currentActivityIndex];
          context.ScheduleActivity(nextChild, _onChildComplete);
    
          _currentIndex.Set(context, ++currentActivityIndex);
        }
    
        #endregion Methods
      }
    }
    
    
    Friday, March 4, 2011 1:12 PM

Answers

  • Hi,

    You see the error might because you didnt expose your implementation variable in your CacheMetadata() method. You can use below code to do it:

    metadata.AddImplementationVariable(_currentIndex);

    For more infomation about exposing data with CacheMetadata, please refer to http://msdn.microsoft.com/zh-cn/library/gg427636.aspx


    This posting is provided "AS IS" and confers no rights or warranties.
    • Marked as answer by Andrew_Zhu Friday, March 11, 2011 2:01 AM
    Friday, March 4, 2011 4:02 PM
  • Hi,

    Please try delete 
         base.CacheMetadata(metadata);
    And add Varibles and Arguments manually. if you defined a Variable collection, you can also add the whole collection in CacheMetadata method:

      metadata.SetImplementationVariablesCollection(Variables);

    Hope this helps
    Regards
        

     

     

     


    MSDN Community Support
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    This posting is provided "AS IS" with no warranties, and confers no rights. My Blog: http://xhinker.com
    Microsoft Windows Workflow Foundation 4.0 Cookbook
    • Marked as answer by Andrew_Zhu Friday, March 11, 2011 2:01 AM
    Tuesday, March 8, 2011 3:36 AM

All replies

  • Hi,

    You see the error might because you didnt expose your implementation variable in your CacheMetadata() method. You can use below code to do it:

    metadata.AddImplementationVariable(_currentIndex);

    For more infomation about exposing data with CacheMetadata, please refer to http://msdn.microsoft.com/zh-cn/library/gg427636.aspx


    This posting is provided "AS IS" and confers no rights or warranties.
    • Marked as answer by Andrew_Zhu Friday, March 11, 2011 2:01 AM
    Friday, March 4, 2011 4:02 PM
  • Hi,

    Please try delete 
         base.CacheMetadata(metadata);
    And add Varibles and Arguments manually. if you defined a Variable collection, you can also add the whole collection in CacheMetadata method:

      metadata.SetImplementationVariablesCollection(Variables);

    Hope this helps
    Regards
        

     

     

     


    MSDN Community Support
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    This posting is provided "AS IS" with no warranties, and confers no rights. My Blog: http://xhinker.com
    Microsoft Windows Workflow Foundation 4.0 Cookbook
    • Marked as answer by Andrew_Zhu Friday, March 11, 2011 2:01 AM
    Tuesday, March 8, 2011 3:36 AM