/// <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));
 }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }