locked
CodeActivity<T> inside custom composition activity RRS feed

  • Question

  • Hi Guys,

    In my activity I have a list of CodeActivity<T> activities to execute. How can I accumulate all the values returned from these activities?

    Initially I was thinking of doing something like:

      public class Composite : NativeActivity
      {
        public Sequence InnerSequence { get; set; }
    
        public Composite(IList<CodeActivity<int>> activities)
        {
          this.InnerSequence = GetSequence(activities);
        }
    
        private Sequence GetSequence(IList<CodeActivity<int>> activities)
        {
          var sequence = new Sequence();
          foreach (var activity in activities)
            sequence.Activities.Add(activity);
    
          return sequence;
        }
    
        protected override void Execute(NativeActivityContext context)
        {
          context.ScheduleActivity(this.InnerSequence);
    
          //this doesn't work
          foreach(var activity in this.InnerSequence.Activities.Cast<CodeActivity<int>>()) 
          {
            var value = activity.Result.Get(context);
          }
        }
      }

    but it doesn't work, of course.

    How can I get these results properly?

     

    Thanks,

    Alexey.


    MCP, MCAD
    Tuesday, July 6, 2010 2:10 PM

Answers

  • Yes, something like this...

    I end up with the following code:

    	public class AggregateSequence<T> : NativeActivity<Collection<T>>
    	{
    		private readonly Variable<Collection<T>> _result = new Variable<Collection<T>>();
    		private readonly Variable<int> _indexToExecute = new Variable<int>();
    
    		private Collection<Activity> _activities;
    		public Collection<Activity> Activities
    		{
    			get { return _activities ?? (_activities = new Collection<Activity>()); }
    		}
    
    		private Collection<Variable> _variables;
    		public Collection<Variable> Variables
    		{
    			get { return _variables ?? (_variables = new Collection<Variable>()); }
    		}
    
    		protected override void CacheMetadata(NativeActivityMetadata metadata)
    		{
    			metadata.AddImplementationVariable(_result);
    			metadata.AddImplementationVariable(_indexToExecute);
    			metadata.SetImplementationChildrenCollection(this.Activities);
    			metadata.SetVariablesCollection(Variables);
    		}
    
    		protected override void Execute(NativeActivityContext context)
    		{
    			_indexToExecute.Set(context, 0);
    			ScheduleNextActivity(context);
    		}
    
    		private void ScheduleNextActivity(NativeActivityContext context)
    		{
    			var index = _indexToExecute.Get(context);
    
    			if (index < this.Activities.Count)
    			{
    				var activity = this.Activities[index];
    
    				var activityWithOneResult = activity as NativeActivity<T>;
    				var activityWithManyResults = activity as NativeActivity<ICollection<T>>;
    
    				if (activityWithOneResult != null)
    					context.ScheduleActivity(activityWithOneResult, ActivityCompletedCallback);
    				else if (activityWithManyResults != null)
    					context.ScheduleActivity(activityWithManyResults, ActivityCompletedCallback);
    				else
    					context.ScheduleActivity(activity, ActivityCompletedCallback);
    
    				_indexToExecute.Set(context, index + 1);
    			}
    			else
    			{
    				context.SetValue(this.Result, _result.Get(context));
    			}
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance, T value)
    		{
    			var result = _result.Get(context) ?? new Collection<T>();
    			result.Add(value);
    
    			ScheduleNextActivity(context);
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance, ICollection<T> value)
    		{
    			if (value != null && value.Count > 0)
    			{
    				var result = _result.Get(context) ?? new Collection<T>();
    				foreach (var item in value) result.Add(item);
    			}
    
    			ScheduleNextActivity(context);
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance)
    		{
    			ScheduleNextActivity(context);
    		}
    	}


    MCP, MCAD
    • Marked as answer by Alexey Raga Thursday, July 8, 2010 8:30 AM
    Thursday, July 8, 2010 8:30 AM

All replies

  • Hi,

    What do you want to do with the aggregated outputs from the code activites? consume them within the custom activity, or return out the list as an output argument of the activity?

    I've got a couple of ideas, let me try them out and I'll get back with you.

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    Tuesday, July 6, 2010 4:03 PM
  • Hi, Alexey

    Here is a custom composite activity sample:
    MyCompositeActivity:

        public class MyCompositeActivity:NativeActivity {

            public Collection<Activity> Activities = new Collection<Activity>();

            int activityCounter = 0;

            protected override void CacheMetadata(NativeActivityMetadata metadata) {

                base.CacheMetadata(metadata);

                foreach (var activity in Activities) {

                    metadata.AddImplementationChild(activity);

                }

            }

            protected override void Execute(NativeActivityContext context) {

                ScheduleActivities(context);

            }

            void ScheduleActivities(NativeActivityContext context) {

                if(activityCounter<Activities.Count)

                    context.ScheduleActivity(this.Activities[activityCounter++],OnActivityCompleted);

            }

            void OnActivityCompleted(NativeActivityContext context, ActivityInstance completedInstance) {

                ScheduleActivities(context);

            }

        }

     

    Host:

        Activity workflow = new MyCompositeActivity() {

             Activities ={

                  new WriteLine{Text="good1"},

                  new WriteLine{Text="good2"},

                  new WriteLine{Text="good3"}

             }

        };

        WorkflowInvoker.Invoke(workflow);

    For more deep understand, please also check this article:
    http://blogs.msdn.com/b/flow/archive/2010/01/31/workflow-foundation-4-0-activity-model-ii.aspx

    Hope this  helps
    Regards


    This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft Online Community Support. My Blog:http://xhinker.com
    Thursday, July 8, 2010 7:29 AM
  • Yes, something like this...

    I end up with the following code:

    	public class AggregateSequence<T> : NativeActivity<Collection<T>>
    	{
    		private readonly Variable<Collection<T>> _result = new Variable<Collection<T>>();
    		private readonly Variable<int> _indexToExecute = new Variable<int>();
    
    		private Collection<Activity> _activities;
    		public Collection<Activity> Activities
    		{
    			get { return _activities ?? (_activities = new Collection<Activity>()); }
    		}
    
    		private Collection<Variable> _variables;
    		public Collection<Variable> Variables
    		{
    			get { return _variables ?? (_variables = new Collection<Variable>()); }
    		}
    
    		protected override void CacheMetadata(NativeActivityMetadata metadata)
    		{
    			metadata.AddImplementationVariable(_result);
    			metadata.AddImplementationVariable(_indexToExecute);
    			metadata.SetImplementationChildrenCollection(this.Activities);
    			metadata.SetVariablesCollection(Variables);
    		}
    
    		protected override void Execute(NativeActivityContext context)
    		{
    			_indexToExecute.Set(context, 0);
    			ScheduleNextActivity(context);
    		}
    
    		private void ScheduleNextActivity(NativeActivityContext context)
    		{
    			var index = _indexToExecute.Get(context);
    
    			if (index < this.Activities.Count)
    			{
    				var activity = this.Activities[index];
    
    				var activityWithOneResult = activity as NativeActivity<T>;
    				var activityWithManyResults = activity as NativeActivity<ICollection<T>>;
    
    				if (activityWithOneResult != null)
    					context.ScheduleActivity(activityWithOneResult, ActivityCompletedCallback);
    				else if (activityWithManyResults != null)
    					context.ScheduleActivity(activityWithManyResults, ActivityCompletedCallback);
    				else
    					context.ScheduleActivity(activity, ActivityCompletedCallback);
    
    				_indexToExecute.Set(context, index + 1);
    			}
    			else
    			{
    				context.SetValue(this.Result, _result.Get(context));
    			}
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance, T value)
    		{
    			var result = _result.Get(context) ?? new Collection<T>();
    			result.Add(value);
    
    			ScheduleNextActivity(context);
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance, ICollection<T> value)
    		{
    			if (value != null && value.Count > 0)
    			{
    				var result = _result.Get(context) ?? new Collection<T>();
    				foreach (var item in value) result.Add(item);
    			}
    
    			ScheduleNextActivity(context);
    		}
    
    		private void ActivityCompletedCallback(NativeActivityContext context, ActivityInstance instance)
    		{
    			ScheduleNextActivity(context);
    		}
    	}


    MCP, MCAD
    • Marked as answer by Alexey Raga Thursday, July 8, 2010 8:30 AM
    Thursday, July 8, 2010 8:30 AM