//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.Activities.Presentation.Internal.PropertyEditing.Model { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text; using System.Windows.Markup; using System.Activities.Presentation.Model; using System.Activities.Presentation.PropertyEditing; // // Static class full of useful helpers // internal static class ModelUtilities { public static Type GetPropertyType(IEnumerable propertySet) { // all the ModelProperty should be of the same type, so returning the first type. foreach (ModelProperty property in propertySet) { return property.PropertyType; } return null; } // // Compares the name and Type of the specified ModelProperties, // returning true if they are equal. // // ModelProperty A // ModelProperty B // True if the names and Types of the specified ModelProperties // match, false otherwise. public static bool AreEquivalent(ModelProperty a, ModelProperty b) { return object.Equals(a.Name, b.Name) && object.Equals(a.PropertyType, b.PropertyType); } // // Gets the underlying value object of the specified ModelProperty. MarkupExtensions // (resources and such) will be returned as they are, with the exception of NullExtension, // which will be returned as null. // // ModelProperty to ---- open (can be null) // Underlying value object, if any public static object GetSafeRawValue(ModelProperty property) { return GetSafeValue(property, false); } // // Gets the underlying computed value object of the specified ModelProperty. MarkupExtensions // (resources and such) will be resolved into their final value. // // ModelProperty to ---- open (can be null) // Underlying value object, if any public static object GetSafeComputedValue(ModelProperty property) { return GetSafeValue(property, true); } private static object GetSafeValue(ModelProperty property, bool resolveReferences) { if (property == null) { return null; } object value; // We have to special case TextBlock due to IAddChild behavior with Text and Inlines if (resolveReferences && !(typeof(System.Windows.Controls.TextBlock).IsAssignableFrom(property.Parent.ItemType) && property.Name.Equals(System.Windows.Controls.TextBlock.TextProperty.Name))) { value = property.ComputedValue; } else { value = property.Value == null ? null : property.Value.GetCurrentValue(); } if (value == null || value.GetType().Equals(typeof(NullExtension))) { return null; } return value; } // // Looks for the x:Name or Name property of the given PropertyValue and returns it if found. // Note: this method is expensive because it evaluates all the sub-properties of the given // PropertyValue. // // PropertyValue instance to look at // Name if the PropertyValue defines one, null otherwise public static string GetPropertyName(PropertyValue propertyValue) { if (propertyValue == null) { return null; } if (propertyValue.HasSubProperties) { PropertyEntry nameProperty = propertyValue.SubProperties["Name"]; if (nameProperty != null) { return nameProperty.PropertyValue.StringValue; } } return null; } // // Returns ',' separated property name for sub-properties, going all the way // to the root ancestor in the property editing OM. (ie. you get strings // such as 'ContextMenu,IsEnabled' instead of just 'IsEnabled'. // // Property to get the name of // ',' separated property name for sub-properties public static string GetSubPropertyHierarchyPath(PropertyEntry property) { if (property == null) { return null; } if (property.ParentValue == null) { return property.PropertyName; } StringBuilder sb = new StringBuilder(); do { if (sb.Length > 0) { sb.Insert(0, ','); } sb.Insert(0, property.PropertyName); property = property.ParentValue == null ? null : property.ParentValue.ParentProperty; } while (property != null && !(property is ModelPropertyIndexer)); return sb.ToString(); } // // Same as GetSubPropertyHierarchyPath(), but it looks up a cached version // of this path, if one exists, or calculates one from scratch and caches it // if it doesn't. // // Property to get the name of // ',' separated property name for sub-properties public static string GetCachedSubPropertyHierarchyPath(PropertyEntry property) { ModelPropertyEntry mpe = property as ModelPropertyEntry; return mpe == null ? GetSubPropertyHierarchyPath(property) : mpe.SubPropertyHierarchyPath; } // // Determines whether the specified type is implement generic Ilist interface. // // The type. // // true if the specified type is implement generic Ilist interface;otherwise, false. // public static bool ImplementsIList(Type type) { bool ret = false; if (!type.IsGenericType) { ret = false; } Type[] interfaceTypes = type.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IList<>)) { ret = true; break; } } return ret; } // // Determines whether the specified type is implement generic ICollection interface. // // The type. // // true if the specified type is implement generic ICollection interface;otherwise, false. // public static bool ImplementsICollection(Type type) { bool ret = false; if (!type.IsGenericType) { ret = false; } Type[] interfaceTypes = type.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>)) { ret = true; break; } } return ret; } // // Tries to determine the common type ancestor of the specified types // // Type 1 // Type 2 // Common ancestor Type, if any public static Type GetCommonAncestor(Type t1, Type t2) { if (t1 == null || t2 == null) { return null; } if (t1 == typeof(object) || t2 == typeof(object)) { return typeof(object); } if (t1.IsAssignableFrom(t2)) { return t1; } while (t2 != typeof(object)) { if (t2.IsAssignableFrom(t1)) { return t2; } t2 = t2.BaseType; } return typeof(object); } } }