/// <summary> /// Returns a dependency object for the given value. /// </summary> private static DependencyObject FromObj(object value) { // This indirection is necessary to support // the "association" feature of type descriptor. This feature // alows one object to mimic the API of another. return((DependencyObject)TypeDescriptor.GetAssociation(typeof(DependencyObject), value)); }
public void GetAssociationReturnsExpectedObject() { var primaryObject = new DescriptorTestComponent(); var secondaryObject = new MockEventDescriptor(); TypeDescriptor.CreateAssociation(primaryObject, secondaryObject); var associatedObject = TypeDescriptor.GetAssociation(secondaryObject.GetType(), primaryObject); Assert.IsType(secondaryObject.GetType(), associatedObject); Assert.Equal(secondaryObject, associatedObject); }
public void GetAssociationReturnsDesigner() { var designer = new MockDesigner(); var designerHost = new MockDesignerHost(); var component = new DescriptorTestComponent(); designerHost.AddDesigner(component, designer); component.AddService(typeof(IDesignerHost), designerHost); object associatedObject = TypeDescriptor.GetAssociation(designer.GetType(), component); Assert.IsType <MockDesigner>(associatedObject); Assert.Same(designer, associatedObject); }
public void RemoveSingleAssociation() { var primaryObject = new DescriptorTestComponent(); var firstAssociatedObject = new MockEventDescriptor(); var secondAssociatedObject = new MockPropertyDescriptor(); TypeDescriptor.CreateAssociation(primaryObject, firstAssociatedObject); TypeDescriptor.CreateAssociation(primaryObject, secondAssociatedObject); TypeDescriptor.RemoveAssociation(primaryObject, firstAssociatedObject); // the second association should remain var secondAssociation = TypeDescriptor.GetAssociation(secondAssociatedObject.GetType(), primaryObject); Assert.Equal(secondAssociatedObject, secondAssociation); // the first association should not var firstAssociation = TypeDescriptor.GetAssociation(firstAssociatedObject.GetType(), primaryObject); Assert.NotEqual(firstAssociatedObject, firstAssociation); }
public void RemoveAssociationsRemovesAllAssociations() { var primaryObject = new DescriptorTestComponent(); var firstAssociatedObject = new MockEventDescriptor(); var secondAssociatedObject = new MockPropertyDescriptor(); TypeDescriptor.CreateAssociation(primaryObject, firstAssociatedObject); TypeDescriptor.CreateAssociation(primaryObject, secondAssociatedObject); TypeDescriptor.RemoveAssociations(primaryObject); // GetAssociation never returns null. The default implementation returns the // primary object when an association doesn't exist. This isn't documented, // however, so here we only verify that the formerly associated objects aren't returned. var firstAssociation = TypeDescriptor.GetAssociation(firstAssociatedObject.GetType(), primaryObject); Assert.NotEqual(firstAssociatedObject, firstAssociation); var secondAssociation = TypeDescriptor.GetAssociation(secondAssociatedObject.GetType(), primaryObject); Assert.NotEqual(secondAssociatedObject, secondAssociation); }
/// <summary> /// Returns a collection of properties for our object. We first rely on base /// CLR properties and then we attempt to match these with dependency properties. /// </summary> public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { // We have two code paths here based on filtered attributes. An attribute // filter is just a notificaiton of a filter, it doesn't actually perform // the filter. Because the default PropertyFilterAttribute is PropertyFilter.All, // it acts as a nice "don't care" in later filtering stages that TypeDescriptor // may apply. That means that regardless of the filter value, we don't have // to fiddle with adding the attribute to the property descriptor. PropertyFilterOptions filter = PropertyFilterOptions.Valid | PropertyFilterOptions.SetValues; if (attributes != null) { foreach (Attribute attr in attributes) { PropertyFilterAttribute filterAttr = attr as PropertyFilterAttribute; if (filterAttr != null) { filter = filterAttr.Filter; break; } } } // If no filter is set, or if the only filter is for "invalid" properties, // there's no work to do. if (filter == PropertyFilterOptions.None || filter == PropertyFilterOptions.Invalid) { return(PropertyDescriptorCollection.Empty); } // Value used during filtering. Because direct properties are always // returned for .Valid and .All, the only case we're directly interested // in is when filter exactly equals SetValues. DependencyObject filterValue; if (filter == PropertyFilterOptions.SetValues) { if (_instance == null) { return(PropertyDescriptorCollection.Empty); } filterValue = (DependencyObject)TypeDescriptor.GetAssociation(_objectType, _instance); } else { filterValue = null; } // Note: For a property filter of "SetValues" it would be ideal if we could use // DependencyObject's GetLocalValueEnumerator. Unfortunately, we can't: // // * We still need to scan properties to get the property descriptor that // matches the DP. // // * The enumerator would skip CLR properties that have no backing DP. // // We can still do some optimizations. // First, have we already discovered properties for this type? PropertyDescriptorCollection properties = (PropertyDescriptorCollection)_typeProperties[_objectType]; if (properties == null) { properties = CreateProperties(); lock (_typeProperties) { _typeProperties[_objectType] = properties; } } // Check bit combinations that would yield true in // any case. For non-attached properties, they're all valid, so if // the valid bit is set, we're done. if ((filter & _anySet) == _anySet || (filter & _anyValid) == _anyValid) { return(properties); } // The filter specifies either set or unset values. Debug.Assert((filter & _anySet) == filter, "There is a filtering case we did not account for"); List <PropertyDescriptor> newDescriptors = null; int cnt = properties.Count; for (int idx = 0; idx < cnt; idx++) { PropertyDescriptor prop = properties[idx]; bool shouldSerialize = prop.ShouldSerializeValue(filterValue); bool addProp = shouldSerialize ^ ((filter & _anySet) == PropertyFilterOptions.UnsetValues); if (!addProp) { // Property should be removed. Make sure our newDescriptors array is // up to date for where we need to be if (newDescriptors == null) { newDescriptors = new List <PropertyDescriptor>(cnt); for (int i = 0; i < idx; i++) { newDescriptors.Add(properties[i]); } } } else if (newDescriptors != null) { newDescriptors.Add(prop); } } if (newDescriptors != null) { properties = new PropertyDescriptorCollection(newDescriptors.ToArray(), true); } return(properties); }