Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Workflow.ComponentModel / Shared / Walker.cs
blob1a8c8858e1747e7ca36db34830df9e9de336ad7d
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 //
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\Activities\Common
12 * The two files must be kept in sync. Any change made here must also
13 * be made to WF\Activities\Common\Walker.cs
14 *********************************************************************/
15 namespace System.Workflow.ComponentModel
17 #region Imports
19 using System;
20 using System.Collections;
21 using System.Collections.Generic;
22 using System.Reflection;
23 using System.ComponentModel;
24 using System.Diagnostics.CodeAnalysis;
26 #endregion
28 // Returns true to continue the walk, false to stop.
29 internal delegate void WalkerEventHandler(Walker walker, WalkerEventArgs eventArgs);
31 internal enum WalkerAction
33 Continue = 0,
34 Skip = 1,
35 Abort = 2
37 #region Class WalkerEventArgs
39 internal sealed class WalkerEventArgs : EventArgs
41 private Activity currentActivity = null;
42 private object currentPropertyOwner = null;
43 private PropertyInfo currentProperty = null;
44 private object currentValue = null;
45 private WalkerAction action = WalkerAction.Continue;
47 internal WalkerEventArgs(Activity currentActivity)
49 this.currentActivity = currentActivity;
50 this.currentPropertyOwner = null;
51 this.currentProperty = null;
52 this.currentValue = null;
55 internal WalkerEventArgs(Activity currentActivity, object currentValue, PropertyInfo currentProperty, object currentPropertyOwner)
56 : this(currentActivity)
58 this.currentPropertyOwner = currentPropertyOwner;
59 this.currentProperty = currentProperty;
60 this.currentValue = currentValue;
63 public WalkerAction Action
65 get
67 return this.action;
69 set
71 this.action = value;
75 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
76 public PropertyInfo CurrentProperty
78 get
80 return this.currentProperty;
84 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
85 public object CurrentPropertyOwner
87 get
89 return this.currentPropertyOwner;
93 [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
94 public object CurrentValue
96 get
98 return this.currentValue;
102 public Activity CurrentActivity
106 return this.currentActivity;
111 #endregion
113 internal sealed class Walker
115 #region Members
117 internal event WalkerEventHandler FoundActivity;
118 internal event WalkerEventHandler FoundProperty;
119 private bool useEnabledActivities = false;
121 #endregion
123 #region Methods
125 public Walker()
126 : this(false)
130 public Walker(bool useEnabledActivities)
132 this.useEnabledActivities = useEnabledActivities;
135 public void Walk(Activity seedActivity)
137 Walk(seedActivity, true);
140 public void Walk(Activity seedActivity, bool walkChildren)
142 Queue queue = new Queue();
144 queue.Enqueue(seedActivity);
145 while (queue.Count > 0)
147 Activity activity = queue.Dequeue() as Activity;
149 if (FoundActivity != null)
151 WalkerEventArgs args = new WalkerEventArgs(activity);
152 FoundActivity(this, args);
153 if (args.Action == WalkerAction.Abort)
154 return;
155 if (args.Action == WalkerAction.Skip)
156 continue;
159 if (FoundProperty != null)
161 if (!WalkProperties(activity))
162 return;
165 if (walkChildren && activity is CompositeActivity)
167 if (useEnabledActivities)
169 foreach (Activity activity2 in Design.Helpers.GetAllEnabledActivities((CompositeActivity)activity))
170 queue.Enqueue(activity2);
172 else
174 foreach (Activity activity2 in ((CompositeActivity)activity).Activities)
175 queue.Enqueue(activity2);
181 private bool WalkProperties(Activity seedActivity)
183 return WalkProperties(seedActivity as Activity, seedActivity);
186 public bool WalkProperties(Activity activity, object obj)
188 Activity currentActivity = obj as Activity;
190 PropertyInfo[] props = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
191 foreach (PropertyInfo prop in props)
193 // !!Work around: no indexer property walking
194 if (prop.GetIndexParameters() != null && prop.GetIndexParameters().Length > 0)
195 continue;
197 DesignerSerializationVisibility visibility = GetSerializationVisibility(prop);
198 if (visibility == DesignerSerializationVisibility.Hidden)
199 continue;
201 //Try to see if we have dynamic property associated with the object on the same object
202 //if so then we should compare if the dynamic property values match with the property type
203 //if not we bail out
204 object propValue = null;
205 DependencyProperty dependencyProperty = DependencyProperty.FromName(prop.Name, obj.GetType());
206 if (dependencyProperty != null && currentActivity != null)
208 if (currentActivity.IsBindingSet(dependencyProperty))
209 propValue = currentActivity.GetBinding(dependencyProperty);
210 else
211 propValue = currentActivity.GetValue(dependencyProperty);
213 else
217 propValue = prop.CanRead ? prop.GetValue(obj, null) : null;
219 catch
221 // Eat exceptions that occur while invoking the getter.
225 if (FoundProperty != null)
227 WalkerEventArgs args = new WalkerEventArgs(activity, propValue, prop, obj);
228 FoundProperty(this, args);
229 if (args.Action == WalkerAction.Skip)
230 continue;
231 else if (args.Action == WalkerAction.Abort)
232 return false;
235 if (propValue is IList)
237 //We do not need to reflect on the properties of the list
238 foreach (object childObj in (IList)propValue)
240 if (FoundProperty != null)
242 WalkerEventArgs args = new WalkerEventArgs(activity, childObj, null, propValue);
243 FoundProperty(this, args);
244 if (args.Action == WalkerAction.Skip)
245 continue;
246 else if (args.Action == WalkerAction.Abort)
247 return false;
249 if (childObj != null && IsBrowsableType(childObj.GetType()))
251 if (!WalkProperties(activity, childObj))
252 return false;
256 else if (propValue != null && IsBrowsableType(propValue.GetType()))
258 if (!WalkProperties(activity, propValue))
259 return false;
262 return true;
265 private static DesignerSerializationVisibility GetSerializationVisibility(PropertyInfo prop)
267 // work around!!! for Activities collection
268 if (prop.DeclaringType == typeof(CompositeActivity) && string.Equals(prop.Name, "Activities", StringComparison.Ordinal))
269 return DesignerSerializationVisibility.Hidden;
271 DesignerSerializationVisibility visibility = DesignerSerializationVisibility.Visible;
272 DesignerSerializationVisibilityAttribute[] visibilityAttrs = (DesignerSerializationVisibilityAttribute[])prop.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true);
273 if (visibilityAttrs.Length > 0)
274 visibility = visibilityAttrs[0].Visibility;
276 return visibility;
279 private static bool IsBrowsableType(Type type)
281 bool browsable = false;
282 BrowsableAttribute[] browsableAttrs = (BrowsableAttribute[])type.GetCustomAttributes(typeof(BrowsableAttribute), true);
283 if (browsableAttrs.Length > 0)
284 browsable = browsableAttrs[0].Browsable;
285 return browsable;
287 #endregion