locked
Why WF4 Constraints are not working with Activity and CodeActivity parent's types RRS feed

  • Question

  • I want to set constraint to activity to prevent adding it to some other activities.
    I have problem with GetParentChain I think. I did everything like in msdn samples:


    I have three activities: MyActivity, SqlNativeActivity and SqlActivity. This classes look like:

    SqlNativeActivity: 

    public sealed class SqlNativeActivity : BaseNativeActivity
        {
            public Activity Activity { get; set; }
    
    		protected override void Execute(NativeActivityContext context)
    		{
    		}
        }
    
        public abstract class BaseNativeActivity : NativeActivity
    	{
    		protected ActivityConstraintsProvider ActivityConstraintsProvider;
    
    		protected abstract override void Execute(NativeActivityContext context);
    	}

    SqlActivity: 

        public sealed class SqlActivity : BaseActivity
        {
            public Activity Activity { get; set; }
        }  
    
        public abstract class BaseActivity : Activity
    	{
    		protected ActivityConstraintsProvider ActivityConstraintsProvider;
    	}


    MyActivity: 

        public sealed class MyActivity : BaseActivity
        {
            public MyActivity()
            {
    			ActivityConstraintsProvider = new ActivityConstraintsProvider();
    			ActivityConstraintsProvider.AddNotAcceptedParentActivity(typeof(SqlActivity));
    			ActivityConstraintsProvider.AddNotAcceptedParentActivity(typeof(SqlNativeActivity));
    			base.Constraints.Add(ActivityConstraintsProvider.CheckParent());
            }
    	} 

    And I wrote ActivityConstraintsProvider in which I define List with not accepted parent types.
    ActivityConstraintsProvider: 

        public class ActivityConstraintsProvider
    	{
    		private List<Type> _notAcceptedParentActivity;
    
    		public void AddNotAcceptedParentActivity(Type type)
    		{
    			if (_notAcceptedParentActivity == null)
    				_notAcceptedParentActivity = new List<Type>();
    
    			_notAcceptedParentActivity.Add(type);
    		}
    
    		public Constraint CheckParent()
    		{
    			var element = new DelegateInArgument<Activity>();
    			var context = new DelegateInArgument<ValidationContext>();
    			var result = new Variable<bool>();
    			var parent = new DelegateInArgument<Activity>();
    
    			var con = new Constraint<Activity>
    			{
    				Body = new ActivityAction<Activity, ValidationContext>
    				{
    					Argument1 = element,
    					Argument2 = context,
    					Handler = new Sequence
    					{
    						Variables =
                            {
                                result 
                            },
    						Activities =
                            {
                                new ForEach<Activity>
                                {                                
                                    Values = new GetParentChain
                                    {
                                        ValidationContext = context                                    
                                    },
                                    Body = new ActivityAction<Activity>
                                    {   
                                        Argument = parent, 
                                        Handler = new If()
                                        {                                          
                                            Condition = new InArgument<bool>((env) => _notAcceptedParentActivity.Contains(parent.Get(env).GetType())),                                        
                                            Then = new Assign<bool>
                                            {
                                                Value = true,
                                                To = result
                                            },
                                        }
                                    }
                                },
                                new AssertValidation
                                {
                                    Assertion = new InArgument<bool> { Expression = new Not<bool, bool> { Operand = result } },
                                    Message = new InArgument<string> ("Decide can't be in Sql"),                                                                
                                }
                            }
    					}
    				}
    			};
    
    			return con;
    		}
    	}

    And finally Main:

        class Program
    	{
    		static void Main()
    		{
    			ValidationResults results;
    
    			Activity wf3 = new SqlActivity
    			{
    				Activity = new Sequence()
    							{
    								Activities = 
    								{
    									new MyActivity
    									{
    									}
    								}
    							}
    			};
    			results = ActivityValidationServices.Validate(wf3);
    			Console.WriteLine("WF3 (SqlActivity):");
    			PrintResults(results);
    
    			//----------------------------------------------------------------
    
    			Activity wf4 = new SqlNativeActivity
    			{
    				Activity = new Sequence()
    							{
    								Activities = 
    								{
    									new MyActivity
    									{
    									}
    								}
    							}
    			};
    			results = ActivityValidationServices.Validate(wf4);
    			Console.WriteLine("WF4 (SqlNativeActivity):");
    			PrintResults(results);
    
    			//----------------------------------------------------------------
    	    }		
    
            static void PrintResults(ValidationResults results)
            {
    			Console.WriteLine();
    
    			if (results.Errors.Count == 0 && results.Warnings.Count == 0)
    			{
    				Console.WriteLine("	No warnings or errors");
    			}
    			else
    			{
    				foreach (ValidationError error in results.Errors)
    				{
    					Console.WriteLine("	Error: " + error.Message);
    				}
    				foreach (ValidationError warning in results.Warnings)
    				{
    					Console.WriteLine("	Warning: " + warning.Message);
    				}
    			}
    			Console.WriteLine();
            }
        }

    And the problem is that if my sql activity is inherites from System.Activities.NativeActivity (SqlNativeActivity) constraints are working very well, but if I define constraints and parent is activity inherites from System.Activities.Activity or System.Activities.CodeActivity constraints validation is not working at all.
    Anybody can help me with my problem?
    Thank you in advance :)



    • Edited by luke1226 Thursday, March 15, 2012 7:17 AM
    Wednesday, March 14, 2012 3:36 PM

Answers

  • This is intentional. The reason is that neither Activity nor CodeActivity is intended to have public child activities as per your scenario. CodeActivity is not intended to have child activities at all, since it has no way to schedule them. Activity has an Implementation property which contains implementation activities (as opposed to public activities), and does not allow you to add any other implementation activities.

    (Your scenario of providing user-customizable child activity tree should be a public child scenario, not an implementation child scenario, because the implementation of your activity is not transparent to your user.)
    Tim

    • Proposed as answer by Tim Lovell-Smith Friday, March 23, 2012 2:26 AM
    • Marked as answer by LeoTang Sunday, March 25, 2012 8:10 AM
    Friday, March 23, 2012 2:26 AM