1 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
4 // WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
5 // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
6 // THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE
7 // AND INFORMATION REMAINS WITH THE USER.
10 /*********************************************************************
11 * NOTE: A copy of this file exists at: WF\Common\Shared
12 * The two files must be kept in sync. Any change made here must also
13 * be made to WF\Common\Shared\Walker.cs
14 *********************************************************************/
15 namespace System.Workflow.Activities.Common
20 using System.Collections;
21 using System.Collections.Generic;
22 using System.Reflection;
23 using System.ComponentModel;
24 using System.Diagnostics.CodeAnalysis;
25 using System.Workflow.ComponentModel;
29 // Returns true to continue the walk, false to stop.
30 internal delegate void WalkerEventHandler(Walker walker, WalkerEventArgs eventArgs);
32 internal enum WalkerAction
38 #region Class WalkerEventArgs
40 internal sealed class WalkerEventArgs : EventArgs
42 private Activity currentActivity = null;
43 private object currentPropertyOwner = null;
44 private PropertyInfo currentProperty = null;
45 private object currentValue = null;
46 private WalkerAction action = WalkerAction.Continue;
48 internal WalkerEventArgs(Activity currentActivity)
50 this.currentActivity = currentActivity;
51 this.currentPropertyOwner = null;
52 this.currentProperty = null;
53 this.currentValue = null;
56 internal WalkerEventArgs(Activity currentActivity, object currentValue, PropertyInfo currentProperty, object currentPropertyOwner)
57 : this(currentActivity)
59 this.currentPropertyOwner = currentPropertyOwner;
60 this.currentProperty = currentProperty;
61 this.currentValue = currentValue;
64 public WalkerAction Action
76 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
77 public PropertyInfo CurrentProperty
81 return this.currentProperty;
85 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
86 public object CurrentPropertyOwner
90 return this.currentPropertyOwner;
94 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
95 public object CurrentValue
99 return this.currentValue;
103 public Activity CurrentActivity
107 return this.currentActivity;
114 internal sealed class Walker
118 internal event WalkerEventHandler FoundActivity;
119 internal event WalkerEventHandler FoundProperty;
120 private bool useEnabledActivities = false;
131 public Walker(bool useEnabledActivities)
133 this.useEnabledActivities = useEnabledActivities;
136 public void Walk(Activity seedActivity)
138 Walk(seedActivity, true);
141 public void Walk(Activity seedActivity, bool walkChildren)
143 Queue queue = new Queue();
145 queue.Enqueue(seedActivity);
146 while (queue.Count > 0)
148 Activity activity = queue.Dequeue() as Activity;
150 if (FoundActivity != null)
152 WalkerEventArgs args = new WalkerEventArgs(activity);
153 FoundActivity(this, args);
154 if (args.Action == WalkerAction.Abort)
156 if (args.Action == WalkerAction.Skip)
160 if (FoundProperty != null)
162 if (!WalkProperties(activity))
166 if (walkChildren && activity is CompositeActivity)
168 if (useEnabledActivities)
170 foreach (Activity activity2 in Helpers.GetAllEnabledActivities((CompositeActivity)activity))
171 queue.Enqueue(activity2);
175 foreach (Activity activity2 in ((CompositeActivity)activity).Activities)
176 queue.Enqueue(activity2);
182 private bool WalkProperties(Activity seedActivity)
184 return WalkProperties(seedActivity as Activity, seedActivity);
187 public bool WalkProperties(Activity activity, object obj)
189 Activity currentActivity = obj as Activity;
191 PropertyInfo[] props = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
192 foreach (PropertyInfo prop in props)
194 // !!Work around: no indexer property walking
195 if (prop.GetIndexParameters() != null && prop.GetIndexParameters().Length > 0)
198 DesignerSerializationVisibility visibility = GetSerializationVisibility(prop);
199 if (visibility == DesignerSerializationVisibility.Hidden)
202 //Try to see if we have dynamic property associated with the object on the same object
203 //if so then we should compare if the dynamic property values match with the property type
205 object propValue = null;
206 DependencyProperty dependencyProperty = DependencyProperty.FromName(prop.Name, obj.GetType());
207 if (dependencyProperty != null && currentActivity != null)
209 if (currentActivity.IsBindingSet(dependencyProperty))
210 propValue = currentActivity.GetBinding(dependencyProperty);
212 propValue = currentActivity.GetValue(dependencyProperty);
218 propValue = prop.CanRead ? prop.GetValue(obj, null) : null;
222 // Eat exceptions that occur while invoking the getter.
226 if (FoundProperty != null)
228 WalkerEventArgs args = new WalkerEventArgs(activity, propValue, prop, obj);
229 FoundProperty(this, args);
230 if (args.Action == WalkerAction.Skip)
232 else if (args.Action == WalkerAction.Abort)
236 if (propValue is IList)
238 //We do not need to reflect on the properties of the list
239 foreach (object childObj in (IList)propValue)
241 if (FoundProperty != null)
243 WalkerEventArgs args = new WalkerEventArgs(activity, childObj, null, propValue);
244 FoundProperty(this, args);
245 if (args.Action == WalkerAction.Skip)
247 else if (args.Action == WalkerAction.Abort)
250 if (childObj != null && IsBrowsableType(childObj.GetType()))
252 if (!WalkProperties(activity, childObj))
257 else if (propValue != null && IsBrowsableType(propValue.GetType()))
259 if (!WalkProperties(activity, propValue))
266 private static DesignerSerializationVisibility GetSerializationVisibility(PropertyInfo prop)
268 // work around!!! for Activities collection
269 if (prop.DeclaringType == typeof(CompositeActivity) && string.Equals(prop.Name, "Activities", StringComparison.Ordinal))
270 return DesignerSerializationVisibility.Hidden;
272 DesignerSerializationVisibility visibility = DesignerSerializationVisibility.Visible;
273 DesignerSerializationVisibilityAttribute[] visibilityAttrs = (DesignerSerializationVisibilityAttribute[])prop.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true);
274 if (visibilityAttrs.Length > 0)
275 visibility = visibilityAttrs[0].Visibility;
280 private static bool IsBrowsableType(Type type)
282 bool browsable = false;
283 BrowsableAttribute[] browsableAttrs = (BrowsableAttribute[])type.GetCustomAttributes(typeof(BrowsableAttribute), true);
284 if (browsableAttrs.Length > 0)
285 browsable = browsableAttrs[0].Browsable;