Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlSerializationWriter.cs
- ImageCodecInfoPrivate.cs
- RedBlackList.cs
- WorkBatch.cs
- IItemProperties.cs
- TryCatchDesigner.xaml.cs
- RightsManagementInformation.cs
- KeyValuePairs.cs
- ThicknessConverter.cs
- ProxyAttribute.cs
- WindowsListViewScroll.cs
- XmlQueryRuntime.cs
- FileAuthorizationModule.cs
- CompiledELinqQueryState.cs
- TableLayoutPanelCellPosition.cs
- SendActivity.cs
- HtmlSelect.cs
- TabItem.cs
- OleServicesContext.cs
- RtfControls.cs
- WebBrowserBase.cs
- PaintEvent.cs
- SaveFileDialog.cs
- Journal.cs
- WebContext.cs
- BaseCollection.cs
- DesignerHelpers.cs
- CacheMemory.cs
- ActivitiesCollection.cs
- HttpApplication.cs
- CellTreeNode.cs
- FunctionDetailsReader.cs
- ObjectStateEntryBaseUpdatableDataRecord.cs
- ObjectDataSourceDesigner.cs
- StrokeCollectionDefaultValueFactory.cs
- Contracts.cs
- ParserOptions.cs
- XmlArrayItemAttribute.cs
- Types.cs
- Function.cs
- NonSerializedAttribute.cs
- DataGridRelationshipRow.cs
- FileDialog.cs
- FixedMaxHeap.cs
- ImportedNamespaceContextItem.cs
- TaskResultSetter.cs
- SmtpFailedRecipientException.cs
- SQLMembershipProvider.cs
- SpellCheck.cs
- RenderingBiasValidation.cs
- GACIdentityPermission.cs
- FixedSOMPageConstructor.cs
- FloaterParagraph.cs
- VectorAnimation.cs
- WebBrowserNavigatingEventHandler.cs
- Point3DAnimationUsingKeyFrames.cs
- VarRemapper.cs
- ButtonBase.cs
- GridItem.cs
- PrincipalPermission.cs
- BuildResultCache.cs
- SqlEnums.cs
- IndexedDataBuffer.cs
- PeerApplicationLaunchInfo.cs
- HtmlElementEventArgs.cs
- PerfCounterSection.cs
- HttpRequest.cs
- SequentialUshortCollection.cs
- ReadOnlyPropertyMetadata.cs
- RootDesignerSerializerAttribute.cs
- storepermissionattribute.cs
- FilterQuery.cs
- DtcInterfaces.cs
- XmlSchemaSequence.cs
- SystemInformation.cs
- ToggleButtonAutomationPeer.cs
- PackageRelationship.cs
- GridViewUpdateEventArgs.cs
- WorkItem.cs
- NCryptNative.cs
- SerialStream.cs
- Track.cs
- DetailsViewRow.cs
- SemaphoreSecurity.cs
- InputLanguageEventArgs.cs
- OdbcParameterCollection.cs
- ValueChangedEventManager.cs
- XmlWellformedWriter.cs
- CookielessData.cs
- SelectionHighlightInfo.cs
- OdbcException.cs
- ComboBox.cs
- XmlSchemaSimpleContent.cs
- DynamicEntity.cs
- WebPartMenu.cs
- WebServiceReceiveDesigner.cs
- MimeAnyImporter.cs
- TableStyle.cs
- OdbcEnvironment.cs
- ConstantSlot.cs