1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.Internal.PropertyEditing.Model
7 using System.Collections.Generic;
8 using System.Diagnostics.CodeAnalysis;
10 using System.Windows.Markup;
11 using System.Activities.Presentation.Model;
12 using System.Activities.Presentation.PropertyEditing;
15 // Static class full of useful helpers
17 internal static class ModelUtilities
19 public static Type GetPropertyType(IEnumerable<ModelProperty> propertySet)
21 // all the ModelProperty should be of the same type, so returning the first type.
22 foreach (ModelProperty property in propertySet)
24 return property.PropertyType;
30 // Compares the name and Type of the specified ModelProperties,
31 // returning true if they are equal.
33 // <param name="a">ModelProperty A</param>
34 // <param name="b">ModelProperty B</param>
35 // <returns>True if the names and Types of the specified ModelProperties
36 // match, false otherwise.</returns>
37 public static bool AreEquivalent(ModelProperty a, ModelProperty b)
39 return object.Equals(a.Name, b.Name) &&
40 object.Equals(a.PropertyType, b.PropertyType);
44 // Gets the underlying value object of the specified ModelProperty. MarkupExtensions
45 // (resources and such) will be returned as they are, with the exception of NullExtension,
46 // which will be returned as null.
48 // <param name="property">ModelProperty to ---- open (can be null)</param>
49 // <returns>Underlying value object, if any</returns>
50 public static object GetSafeRawValue(ModelProperty property)
52 return GetSafeValue(property, false);
56 // Gets the underlying computed value object of the specified ModelProperty. MarkupExtensions
57 // (resources and such) will be resolved into their final value.
59 // <param name="property">ModelProperty to ---- open (can be null)</param>
60 // <returns>Underlying value object, if any</returns>
61 public static object GetSafeComputedValue(ModelProperty property)
63 return GetSafeValue(property, true);
66 private static object GetSafeValue(ModelProperty property, bool resolveReferences)
75 // We have to special case TextBlock due to IAddChild behavior with Text and Inlines
76 if (resolveReferences && !(typeof(System.Windows.Controls.TextBlock).IsAssignableFrom(property.Parent.ItemType) &&
77 property.Name.Equals(System.Windows.Controls.TextBlock.TextProperty.Name)))
79 value = property.ComputedValue;
83 value = property.Value == null ? null : property.Value.GetCurrentValue();
86 if (value == null || value.GetType().Equals(typeof(NullExtension)))
95 // Looks for the x:Name or Name property of the given PropertyValue and returns it if found.
96 // Note: this method is expensive because it evaluates all the sub-properties of the given
99 // <param name="propertyValue">PropertyValue instance to look at</param>
100 // <returns>Name if the PropertyValue defines one, null otherwise</returns>
101 public static string GetPropertyName(PropertyValue propertyValue)
103 if (propertyValue == null)
108 if (propertyValue.HasSubProperties)
110 PropertyEntry nameProperty = propertyValue.SubProperties["Name"];
111 if (nameProperty != null)
113 return nameProperty.PropertyValue.StringValue;
121 // Returns ',' separated property name for sub-properties, going all the way
122 // to the root ancestor in the property editing OM. (ie. you get strings
123 // such as 'ContextMenu,IsEnabled' instead of just 'IsEnabled'.
125 // <param name="property">Property to get the name of</param>
126 // <returns>',' separated property name for sub-properties</returns>
127 public static string GetSubPropertyHierarchyPath(PropertyEntry property)
129 if (property == null)
134 if (property.ParentValue == null)
136 return property.PropertyName;
139 StringBuilder sb = new StringBuilder();
147 sb.Insert(0, property.PropertyName);
148 property = property.ParentValue == null ? null : property.ParentValue.ParentProperty;
150 } while (property != null && !(property is ModelPropertyIndexer));
152 return sb.ToString();
156 // Same as GetSubPropertyHierarchyPath(), but it looks up a cached version
157 // of this path, if one exists, or calculates one from scratch and caches it
160 // <param name="property">Property to get the name of</param>
161 // <returns>',' separated property name for sub-properties</returns>
162 public static string GetCachedSubPropertyHierarchyPath(PropertyEntry property)
164 ModelPropertyEntry mpe = property as ModelPropertyEntry;
165 return mpe == null ? GetSubPropertyHierarchyPath(property) : mpe.SubPropertyHierarchyPath;
169 // Determines whether the specified type is implement generic Ilist interface.
171 // <param name="type">The type.</param>
173 // <c>true</c> if the specified type is implement generic Ilist interface;otherwise, <c>false</c>.
175 public static bool ImplementsIList(Type type)
178 if (!type.IsGenericType)
182 Type[] interfaceTypes = type.GetInterfaces();
183 foreach (Type interfaceType in interfaceTypes)
185 if (interfaceType.IsGenericType &&
186 interfaceType.GetGenericTypeDefinition() == typeof(IList<>))
196 // Determines whether the specified type is implement generic ICollection interface.
198 // <param name="type">The type.</param>
200 // <c>true</c> if the specified type is implement generic ICollection interface;otherwise, <c>false</c>.
202 public static bool ImplementsICollection(Type type)
205 if (!type.IsGenericType)
209 Type[] interfaceTypes = type.GetInterfaces();
210 foreach (Type interfaceType in interfaceTypes)
212 if (interfaceType.IsGenericType &&
213 interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>))
223 // Tries to determine the common type ancestor of the specified types
225 // <param name="t1">Type 1</param>
226 // <param name="t2">Type 2</param>
227 // <returns>Common ancestor Type, if any</returns>
228 public static Type GetCommonAncestor(Type t1, Type t2)
230 if (t1 == null || t2 == null)
235 if (t1 == typeof(object) || t2 == typeof(object))
237 return typeof(object);
240 if (t1.IsAssignableFrom(t2))
245 while (t2 != typeof(object))
247 if (t2.IsAssignableFrom(t1))
255 return typeof(object);