Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / ComponentModel / APCustomTypeDescriptor.cs / 1305600 / APCustomTypeDescriptor.cs
namespace MS.Internal.ComponentModel { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Windows; using System.Windows.Markup; using System.Text; ////// This class is a custom type descriptor for attached dependency properties. We /// could just inherit from the CustomTypeDescriptor class, which does most of the forwarding /// work for us, but these are allocated a lot so we want them to be structs. /// struct APCustomTypeDescriptor : ICustomTypeDescriptor { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// Creates a new APCustomTypeDescriptor. We pass in the custom type descriptor of /// our base provider, which provides is with a default implementation of everything /// we don't override. for us, we want to override only the property mechanism. /// internal APCustomTypeDescriptor(ICustomTypeDescriptor parent, object instance) { _parent = parent; _instance = FromObj(instance); } #endregion Constructors //----------------------------------------------------- // // Public Methods // //----------------------------------------------------- #region Public Methods ////// 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. /// public PropertyDescriptorCollection GetProperties() { return GetProperties(null); } ////// 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. /// public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { // Because attached properties can come and go at any time, // the set of properties we have here always needs to be rebuilt. // 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 (filter == PropertyFilterOptions.None) { return PropertyDescriptorCollection.Empty; } // First, get the set of all known registered properties in the // app domain. GetRegisteredProperties caches its results and // will automatically re-fetch if new properties have been // registered DependencyProperty[] registeredProperties = GetRegisteredProperties(); Type instanceType = _instance.GetType(); // Next, walk through them and see which ones can be attached to this // object. If our filter is specifically SetValues, we can // greatly shortcut the entire process by using the local value // enumerator. ListfilteredProps; if (filter == PropertyFilterOptions.SetValues) { LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator(); filteredProps = new List (localEnum.Count); while(localEnum.MoveNext()) { DependencyProperty dp = localEnum.Current.Property; DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType); // For locally set values, we just want to exclude direct and internal properties. if (!kind.IsDirect && !kind.IsInternal) { DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType); filteredProps.Add(dpProp); } } } else { filteredProps = new List (registeredProperties.Length); foreach (DependencyProperty dp in registeredProperties) { bool addProp = false; DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType); if (kind.IsAttached) { // 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. PropertyFilterOptions anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues; PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid; if ((filter & anySet) == anySet || (filter & anyValid) == anyValid) { addProp = true; } if (!addProp && (filter & anyValid) != 0) { bool canAttach = CanAttachProperty(dp, _instance); addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid); } if (!addProp && (filter & anySet) != 0) { bool shouldSerialize = _instance.ContainsValue(dp); addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues); } } else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal) { // The property is not attached. However, it isn't an internal DP and the user // has requested set values. See if the property is set on the object and include // it if it is. addProp = true; } if (addProp) { DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType); filteredProps.Add(dpProp); } } } PropertyDescriptorCollection properties; properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true); return properties; } // // All methods below simply forward to the parent descriptor. // public AttributeCollection GetAttributes() { return _parent.GetAttributes(); } public string GetClassName() { return _parent.GetClassName(); } public string GetComponentName() { return _parent.GetComponentName(); } public TypeConverter GetConverter() { // We only support public type converters, in order to avoid asserts. TypeConverter typeConverter = _parent.GetConverter(); if( typeConverter.GetType().IsPublic ) { return typeConverter; } else { return null; } } public EventDescriptor GetDefaultEvent() { return _parent.GetDefaultEvent(); } public PropertyDescriptor GetDefaultProperty() { return _parent.GetDefaultProperty(); } public object GetEditor(Type editorBaseType) { return _parent.GetEditor(editorBaseType); } public EventDescriptorCollection GetEvents() { return _parent.GetEvents(); } public EventDescriptorCollection GetEvents(Attribute[] attributes) { return _parent.GetEvents(attributes); } public object GetPropertyOwner(PropertyDescriptor property) { return _parent.GetPropertyOwner(property); } #endregion Public Methods //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods /// /// This method determines if the given property can be attached /// to the given instance. /// private bool CanAttachProperty(DependencyProperty dp, DependencyObject instance) { AttachInfo info = DependencyObjectProvider.GetAttachInfo(dp); return info.CanAttach(instance); } ////// Returns a dependency object for the given value. /// 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); } ////// Returns an array of all registered properties declared in the /// system. /// private DependencyProperty[] GetRegisteredProperties() { DependencyProperty[] registeredProperties; // We keep track of the global dependency property count. // Because DPs are never removed, we use this value to // verify if our cache of registered properties is up to date. // If the count doesn't match our cached count, we re-fetch // all registered properties. lock(_syncLock) { int cacheCnt = _dpCacheCount; int currentCnt = DependencyProperty.RegisteredPropertyCount; if (_dpCacheArray == null || cacheCnt != currentCnt) { ListdpList = new List (currentCnt); lock(DependencyProperty.Synchronized) { foreach(DependencyProperty dp in DependencyProperty.RegisteredProperties) { dpList.Add(dp); } _dpCacheCount = DependencyProperty.RegisteredPropertyCount; _dpCacheArray = dpList.ToArray(); } } registeredProperties = _dpCacheArray; } return registeredProperties; } #endregion Private Methods //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ #region Private Fields private ICustomTypeDescriptor _parent; private DependencyObject _instance; private static object _syncLock = new object(); // Synchronized by "_syncLock" private static int _dpCacheCount = 0; // Synchronized by "_syncLock" private static DependencyProperty[] _dpCacheArray; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. namespace MS.Internal.ComponentModel { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Windows; using System.Windows.Markup; using System.Text; /// /// This class is a custom type descriptor for attached dependency properties. We /// could just inherit from the CustomTypeDescriptor class, which does most of the forwarding /// work for us, but these are allocated a lot so we want them to be structs. /// struct APCustomTypeDescriptor : ICustomTypeDescriptor { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// Creates a new APCustomTypeDescriptor. We pass in the custom type descriptor of /// our base provider, which provides is with a default implementation of everything /// we don't override. for us, we want to override only the property mechanism. /// internal APCustomTypeDescriptor(ICustomTypeDescriptor parent, object instance) { _parent = parent; _instance = FromObj(instance); } #endregion Constructors //----------------------------------------------------- // // Public Methods // //----------------------------------------------------- #region Public Methods ////// 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. /// public PropertyDescriptorCollection GetProperties() { return GetProperties(null); } ////// 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. /// public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { // Because attached properties can come and go at any time, // the set of properties we have here always needs to be rebuilt. // 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 (filter == PropertyFilterOptions.None) { return PropertyDescriptorCollection.Empty; } // First, get the set of all known registered properties in the // app domain. GetRegisteredProperties caches its results and // will automatically re-fetch if new properties have been // registered DependencyProperty[] registeredProperties = GetRegisteredProperties(); Type instanceType = _instance.GetType(); // Next, walk through them and see which ones can be attached to this // object. If our filter is specifically SetValues, we can // greatly shortcut the entire process by using the local value // enumerator. ListfilteredProps; if (filter == PropertyFilterOptions.SetValues) { LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator(); filteredProps = new List (localEnum.Count); while(localEnum.MoveNext()) { DependencyProperty dp = localEnum.Current.Property; DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType); // For locally set values, we just want to exclude direct and internal properties. if (!kind.IsDirect && !kind.IsInternal) { DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType); filteredProps.Add(dpProp); } } } else { filteredProps = new List (registeredProperties.Length); foreach (DependencyProperty dp in registeredProperties) { bool addProp = false; DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType); if (kind.IsAttached) { // 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. PropertyFilterOptions anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues; PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid; if ((filter & anySet) == anySet || (filter & anyValid) == anyValid) { addProp = true; } if (!addProp && (filter & anyValid) != 0) { bool canAttach = CanAttachProperty(dp, _instance); addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid); } if (!addProp && (filter & anySet) != 0) { bool shouldSerialize = _instance.ContainsValue(dp); addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues); } } else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal) { // The property is not attached. However, it isn't an internal DP and the user // has requested set values. See if the property is set on the object and include // it if it is. addProp = true; } if (addProp) { DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType); filteredProps.Add(dpProp); } } } PropertyDescriptorCollection properties; properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true); return properties; } // // All methods below simply forward to the parent descriptor. // public AttributeCollection GetAttributes() { return _parent.GetAttributes(); } public string GetClassName() { return _parent.GetClassName(); } public string GetComponentName() { return _parent.GetComponentName(); } public TypeConverter GetConverter() { // We only support public type converters, in order to avoid asserts. TypeConverter typeConverter = _parent.GetConverter(); if( typeConverter.GetType().IsPublic ) { return typeConverter; } else { return null; } } public EventDescriptor GetDefaultEvent() { return _parent.GetDefaultEvent(); } public PropertyDescriptor GetDefaultProperty() { return _parent.GetDefaultProperty(); } public object GetEditor(Type editorBaseType) { return _parent.GetEditor(editorBaseType); } public EventDescriptorCollection GetEvents() { return _parent.GetEvents(); } public EventDescriptorCollection GetEvents(Attribute[] attributes) { return _parent.GetEvents(attributes); } public object GetPropertyOwner(PropertyDescriptor property) { return _parent.GetPropertyOwner(property); } #endregion Public Methods //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods /// /// This method determines if the given property can be attached /// to the given instance. /// private bool CanAttachProperty(DependencyProperty dp, DependencyObject instance) { AttachInfo info = DependencyObjectProvider.GetAttachInfo(dp); return info.CanAttach(instance); } ////// Returns a dependency object for the given value. /// 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); } ////// Returns an array of all registered properties declared in the /// system. /// private DependencyProperty[] GetRegisteredProperties() { DependencyProperty[] registeredProperties; // We keep track of the global dependency property count. // Because DPs are never removed, we use this value to // verify if our cache of registered properties is up to date. // If the count doesn't match our cached count, we re-fetch // all registered properties. lock(_syncLock) { int cacheCnt = _dpCacheCount; int currentCnt = DependencyProperty.RegisteredPropertyCount; if (_dpCacheArray == null || cacheCnt != currentCnt) { ListdpList = new List (currentCnt); lock(DependencyProperty.Synchronized) { foreach(DependencyProperty dp in DependencyProperty.RegisteredProperties) { dpList.Add(dp); } _dpCacheCount = DependencyProperty.RegisteredPropertyCount; _dpCacheArray = dpList.ToArray(); } } registeredProperties = _dpCacheArray; } return registeredProperties; } #endregion Private Methods //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ #region Private Fields private ICustomTypeDescriptor _parent; private DependencyObject _instance; private static object _syncLock = new object(); // Synchronized by "_syncLock" private static int _dpCacheCount = 0; // Synchronized by "_syncLock" private static DependencyProperty[] _dpCacheArray; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NonValidatingSecurityTokenAuthenticator.cs
- AttachInfo.cs
- ResourceType.cs
- InputMethodStateTypeInfo.cs
- RuleSettingsCollection.cs
- EmbeddedMailObjectsCollection.cs
- StylusPlugin.cs
- SqlCommandBuilder.cs
- DurationConverter.cs
- FacetValueContainer.cs
- ExceptionUtil.cs
- IntSumAggregationOperator.cs
- ConnectionManagementElement.cs
- TextTreeRootTextBlock.cs
- BitmapData.cs
- sitestring.cs
- DeflateEmulationStream.cs
- GridViewUpdateEventArgs.cs
- ListViewSortEventArgs.cs
- MessageSmuggler.cs
- JsonWriter.cs
- ToolStripDropDown.cs
- JapaneseCalendar.cs
- FrameworkEventSource.cs
- GenericPrincipal.cs
- DataServiceStreamProviderWrapper.cs
- ActivationProxy.cs
- RealizationContext.cs
- MobileControlsSectionHandler.cs
- SessionEndingCancelEventArgs.cs
- MimeImporter.cs
- SystemIcons.cs
- StrongNameIdentityPermission.cs
- RenderOptions.cs
- SecurityPermission.cs
- Hyperlink.cs
- ScrollBarRenderer.cs
- EntityParameter.cs
- EventManager.cs
- SettingsAttributes.cs
- WebPartEditorApplyVerb.cs
- EditBehavior.cs
- SocketElement.cs
- DisposableCollectionWrapper.cs
- KeyConverter.cs
- XmlElementAttribute.cs
- DataListItem.cs
- EDesignUtil.cs
- LoginStatusDesigner.cs
- TextServicesPropertyRanges.cs
- XmlSchemaObjectTable.cs
- CodeArrayCreateExpression.cs
- CodeTypeMember.cs
- ScrollPatternIdentifiers.cs
- DefaultParameterValueAttribute.cs
- Stopwatch.cs
- RelatedView.cs
- HandledEventArgs.cs
- FocusWithinProperty.cs
- EntityClassGenerator.cs
- TableLayoutPanel.cs
- SoapHeader.cs
- AsymmetricKeyExchangeDeformatter.cs
- ItemContainerGenerator.cs
- WebPartEditorApplyVerb.cs
- StorageConditionPropertyMapping.cs
- Activator.cs
- AutomationFocusChangedEventArgs.cs
- RadioButtonRenderer.cs
- DynamicPropertyHolder.cs
- CacheAxisQuery.cs
- TimeoutStream.cs
- XmlCharType.cs
- QueryModel.cs
- DSASignatureDeformatter.cs
- webeventbuffer.cs
- HttpServerUtilityBase.cs
- HostedElements.cs
- DeviceContext2.cs
- DBConcurrencyException.cs
- ProfileEventArgs.cs
- DateTimeFormatInfoScanner.cs
- Transactions.cs
- PtsPage.cs
- WebPartAuthorizationEventArgs.cs
- DesignTimeTemplateParser.cs
- InteropBitmapSource.cs
- DispatcherHooks.cs
- ServicePointManager.cs
- CultureMapper.cs
- RegexInterpreter.cs
- NetPipeSectionData.cs
- XmlNodeChangedEventArgs.cs
- SimpleTypeResolver.cs
- ReachBasicContext.cs
- FilteredReadOnlyMetadataCollection.cs
- UserControlParser.cs
- TreeNodeStyle.cs
- DispatcherHookEventArgs.cs
- SvcMapFileSerializer.cs