Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / ComponentModel / DPCustomTypeDescriptor.cs / 1305600 / DPCustomTypeDescriptor.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 dependency properties. We could simply
/// derive from the CustomTypeDescriptor class, but because these are allocated a lot
/// we make them a struct so they are not on the heap.
///
internal struct DPCustomTypeDescriptor : ICustomTypeDescriptor {
//------------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Creates a new DPCustomTypeDescriptor. 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 DPCustomTypeDescriptor(ICustomTypeDescriptor parent, Type objectType, object instance)
{
_parent = parent;
_objectType = objectType;
_instance = instance;
}
#endregion Constructors
//-----------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Returns the component name. To do this, we try to find the
/// RuntimeNamePropertyAttribute on the type. If we find
/// the attribute, we will try to invoke the property to retrieve
/// the component name. If any of these fail, we defer to the
/// parent implementation.
///
public string GetComponentName()
{
if (_instance != null)
{
RuntimeNamePropertyAttribute nameAttr = GetAttributes()[typeof(RuntimeNamePropertyAttribute)] as RuntimeNamePropertyAttribute;
if (nameAttr != null && nameAttr.Name != null)
{
PropertyDescriptor nameProp = GetProperties()[nameAttr.Name];
if (nameProp != null)
{
return nameProp.GetValue(_instance) as string;
}
}
}
return _parent.GetComponentName();
}
///
/// Returns a collection of properties for our object.
///
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)
{
// 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 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(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;
}
//
// All methods below simply forward to the parent descriptor.
//
public AttributeCollection GetAttributes() { return _parent.GetAttributes(); }
public string GetClassName() { return _parent.GetClassName(); }
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 new TypeConverter();
}
}
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
//------------------------------------------------------
//
// Internal Methods
//
//-----------------------------------------------------
#region Internal Methods
///
/// This method is called when we should clear our cached state. The cache
/// may become invalid if someone adds additional type description providers.
///
internal static void ClearCache()
{
lock (_propertyMap)
{
_propertyMap.Clear();
}
lock(_typeProperties)
{
_typeProperties.Clear();
}
}
#endregion Internal Methods
//------------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
//
// Creates the property descriptor collection for this type. The return
// value is all properties that are exposed on this type.
//
private PropertyDescriptorCollection CreateProperties()
{
PropertyDescriptorCollection baseProps = _parent.GetProperties();
List newDescriptors = new List(baseProps.Count);
for (int idx = 0; idx < baseProps.Count; idx++)
{
PropertyDescriptor prop = baseProps[idx];
DependencyObjectPropertyDescriptor dpProp;
DependencyProperty dp = null;
bool inMap;
lock(_propertyMap)
{
inMap = _propertyMap.TryGetValue(prop, out dpProp);
}
if (inMap && dpProp != null)
{
// We need to verify that this property descriptor contains the correct DP.
// We can get the wrong one if a descendant of the type introducing the
// CLR property associates a different DP to itself with the same name.
dp = DependencyProperty.FromName(prop.Name, _objectType);
if (dp != dpProp.DependencyProperty)
{
dpProp = null;
}
else
{
// We also need to verify that the property metadata for dpProp matches
// our object type's metadata
if (dpProp.Metadata != dp.GetMetadata(_objectType))
{
dpProp = null;
}
}
}
if (dpProp == null)
{
// Either the property wasn't in the map or the one that was in there
// can't work for this type. Make a new property if this property is
// backed by a DP. Since we only care about direct dependency properties
// we can short circuit FromName for all properties on types that do
// not derive from DependencyObject. Also, if we already got a DP out of
// the map we can skip the dependency object check on the property, since
// the fact that we got a dp means that there used to be something in the map
// so the component type is already a DependencyObject.
if (dp != null || typeof(DependencyObject).IsAssignableFrom(prop.ComponentType))
{
if (dp == null)
{
dp = DependencyProperty.FromName(prop.Name, _objectType);
}
if (dp != null)
{
dpProp = new DependencyObjectPropertyDescriptor(prop, dp, _objectType);
}
}
// Now insert the new property in our map. Note that we will
// insert a null value into the map if this property descriptor
// had no backing DP so we don't go through this work twice.
if (!inMap)
{
lock(_propertyMap)
{
_propertyMap[prop] = dpProp;
}
}
}
// If we found a dependency property desecriptor for this property,
// use it as our new property.
if (dpProp != null)
{
prop = dpProp;
}
newDescriptors.Add(prop);
}
return new PropertyDescriptorCollection(newDescriptors.ToArray(), true);
}
#endregion Private Methods
//-----------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
#region Private Fields
private ICustomTypeDescriptor _parent;
private Type _objectType;
private object _instance;
// Synchronized by "_propertyMap"
private static Dictionary _propertyMap =
new Dictionary(new PropertyDescriptorComparer());
// Synchronized by "_typeProperties"
private static Hashtable _typeProperties = new Hashtable();
private const PropertyFilterOptions _anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues;
private const PropertyFilterOptions _anyValid = PropertyFilterOptions.Valid;
#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 dependency properties. We could simply
/// derive from the CustomTypeDescriptor class, but because these are allocated a lot
/// we make them a struct so they are not on the heap.
///
internal struct DPCustomTypeDescriptor : ICustomTypeDescriptor {
//------------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Creates a new DPCustomTypeDescriptor. 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 DPCustomTypeDescriptor(ICustomTypeDescriptor parent, Type objectType, object instance)
{
_parent = parent;
_objectType = objectType;
_instance = instance;
}
#endregion Constructors
//-----------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Returns the component name. To do this, we try to find the
/// RuntimeNamePropertyAttribute on the type. If we find
/// the attribute, we will try to invoke the property to retrieve
/// the component name. If any of these fail, we defer to the
/// parent implementation.
///
public string GetComponentName()
{
if (_instance != null)
{
RuntimeNamePropertyAttribute nameAttr = GetAttributes()[typeof(RuntimeNamePropertyAttribute)] as RuntimeNamePropertyAttribute;
if (nameAttr != null && nameAttr.Name != null)
{
PropertyDescriptor nameProp = GetProperties()[nameAttr.Name];
if (nameProp != null)
{
return nameProp.GetValue(_instance) as string;
}
}
}
return _parent.GetComponentName();
}
///
/// Returns a collection of properties for our object.
///
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)
{
// 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 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(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;
}
//
// All methods below simply forward to the parent descriptor.
//
public AttributeCollection GetAttributes() { return _parent.GetAttributes(); }
public string GetClassName() { return _parent.GetClassName(); }
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 new TypeConverter();
}
}
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
//------------------------------------------------------
//
// Internal Methods
//
//-----------------------------------------------------
#region Internal Methods
///
/// This method is called when we should clear our cached state. The cache
/// may become invalid if someone adds additional type description providers.
///
internal static void ClearCache()
{
lock (_propertyMap)
{
_propertyMap.Clear();
}
lock(_typeProperties)
{
_typeProperties.Clear();
}
}
#endregion Internal Methods
//------------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
//
// Creates the property descriptor collection for this type. The return
// value is all properties that are exposed on this type.
//
private PropertyDescriptorCollection CreateProperties()
{
PropertyDescriptorCollection baseProps = _parent.GetProperties();
List newDescriptors = new List(baseProps.Count);
for (int idx = 0; idx < baseProps.Count; idx++)
{
PropertyDescriptor prop = baseProps[idx];
DependencyObjectPropertyDescriptor dpProp;
DependencyProperty dp = null;
bool inMap;
lock(_propertyMap)
{
inMap = _propertyMap.TryGetValue(prop, out dpProp);
}
if (inMap && dpProp != null)
{
// We need to verify that this property descriptor contains the correct DP.
// We can get the wrong one if a descendant of the type introducing the
// CLR property associates a different DP to itself with the same name.
dp = DependencyProperty.FromName(prop.Name, _objectType);
if (dp != dpProp.DependencyProperty)
{
dpProp = null;
}
else
{
// We also need to verify that the property metadata for dpProp matches
// our object type's metadata
if (dpProp.Metadata != dp.GetMetadata(_objectType))
{
dpProp = null;
}
}
}
if (dpProp == null)
{
// Either the property wasn't in the map or the one that was in there
// can't work for this type. Make a new property if this property is
// backed by a DP. Since we only care about direct dependency properties
// we can short circuit FromName for all properties on types that do
// not derive from DependencyObject. Also, if we already got a DP out of
// the map we can skip the dependency object check on the property, since
// the fact that we got a dp means that there used to be something in the map
// so the component type is already a DependencyObject.
if (dp != null || typeof(DependencyObject).IsAssignableFrom(prop.ComponentType))
{
if (dp == null)
{
dp = DependencyProperty.FromName(prop.Name, _objectType);
}
if (dp != null)
{
dpProp = new DependencyObjectPropertyDescriptor(prop, dp, _objectType);
}
}
// Now insert the new property in our map. Note that we will
// insert a null value into the map if this property descriptor
// had no backing DP so we don't go through this work twice.
if (!inMap)
{
lock(_propertyMap)
{
_propertyMap[prop] = dpProp;
}
}
}
// If we found a dependency property desecriptor for this property,
// use it as our new property.
if (dpProp != null)
{
prop = dpProp;
}
newDescriptors.Add(prop);
}
return new PropertyDescriptorCollection(newDescriptors.ToArray(), true);
}
#endregion Private Methods
//-----------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
#region Private Fields
private ICustomTypeDescriptor _parent;
private Type _objectType;
private object _instance;
// Synchronized by "_propertyMap"
private static Dictionary _propertyMap =
new Dictionary(new PropertyDescriptorComparer());
// Synchronized by "_typeProperties"
private static Hashtable _typeProperties = new Hashtable();
private const PropertyFilterOptions _anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues;
private const PropertyFilterOptions _anyValid = PropertyFilterOptions.Valid;
#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
- TextServicesCompartmentEventSink.cs
- DefaultBinder.cs
- WindowsStartMenu.cs
- AnimationLayer.cs
- _ProxyRegBlob.cs
- AppDomainManager.cs
- AutomationPattern.cs
- ArgumentException.cs
- ReflectEventDescriptor.cs
- XsltFunctions.cs
- GeneratedCodeAttribute.cs
- LinearQuaternionKeyFrame.cs
- NamespaceEmitter.cs
- WindowVisualStateTracker.cs
- QilChoice.cs
- OptimalTextSource.cs
- RadialGradientBrush.cs
- TextDecorationUnitValidation.cs
- ValidatorCompatibilityHelper.cs
- SiteMapNode.cs
- BindStream.cs
- UnhandledExceptionEventArgs.cs
- DoubleCollection.cs
- UrlAuthFailedErrorFormatter.cs
- SettingsPropertyIsReadOnlyException.cs
- ResourceDictionaryCollection.cs
- DispatcherTimer.cs
- QueryCursorEventArgs.cs
- ConfigXmlAttribute.cs
- EmptyImpersonationContext.cs
- SessionStateUtil.cs
- EntityCommandExecutionException.cs
- CapabilitiesAssignment.cs
- ComponentEditorPage.cs
- ContextMarshalException.cs
- TreeViewHitTestInfo.cs
- ClientTarget.cs
- XsdDataContractImporter.cs
- SerialPinChanges.cs
- XmlArrayAttribute.cs
- ReadOnlyNameValueCollection.cs
- EntityDataSourceDataSelection.cs
- TreeNode.cs
- LocationSectionRecord.cs
- Style.cs
- SqlDataSourceSelectingEventArgs.cs
- ProgressChangedEventArgs.cs
- FormatVersion.cs
- PropertyFilterAttribute.cs
- BasicBrowserDialog.cs
- MenuItem.cs
- URLAttribute.cs
- ProfileSettings.cs
- HttpContext.cs
- CompensationToken.cs
- HtmlInputButton.cs
- SByteConverter.cs
- XmlDocument.cs
- WebPartRestoreVerb.cs
- RightsManagementEncryptionTransform.cs
- OracleParameterCollection.cs
- EntitySet.cs
- WebPartEditorApplyVerb.cs
- WebBrowsableAttribute.cs
- PassportAuthentication.cs
- CodeAssignStatement.cs
- ToolbarAUtomationPeer.cs
- EditBehavior.cs
- ManipulationPivot.cs
- DataObjectMethodAttribute.cs
- OrderedDictionary.cs
- TextDecorationCollection.cs
- ParameterBuilder.cs
- EncoderParameters.cs
- ThemeDirectoryCompiler.cs
- InlinedAggregationOperatorEnumerator.cs
- CroppedBitmap.cs
- FontFaceLayoutInfo.cs
- RequestSecurityTokenForRemoteTokenFactory.cs
- ObsoleteAttribute.cs
- Zone.cs
- ContentHostHelper.cs
- TextTreeInsertUndoUnit.cs
- DerivedKeySecurityToken.cs
- ContextQuery.cs
- SessionParameter.cs
- BitmapPalette.cs
- XamlSerializerUtil.cs
- Crypto.cs
- SetterBase.cs
- Membership.cs
- XmlReaderSettings.cs
- TimeSpanValidatorAttribute.cs
- ClrProviderManifest.cs
- SQLDouble.cs
- CodeSubDirectory.cs
- SoapWriter.cs
- WebPartExportVerb.cs
- XamlTypeMapper.cs
- GrammarBuilderPhrase.cs