Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / Primitives / ElementMarkupObject.cs / 1305600 / ElementMarkupObject.cs
//------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ElementMarkupObject.cs // // Contents: MarkupObject and MarkupProperty implementation for // DependencyObject // // Created: 04/28/2005 [....] // // // Class hierarchy in this file: // // (MarkupObject) // ElementMarkupObject // // (MarkupProperty) // ElementPropertyBase // ElementObjectPropertyBase // ElementProperty // ElementPseudoPropertyBase // ElementKey // ElementConstructorArgument // ElementItemsPseudoProperty // ElementDictionaryItemsPseudoProperty // ElementStringValueProperty // //----------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Text; using System.Windows; using System.Windows.Data; using System.Windows.Markup; using System.Windows.Documents; namespace System.Windows.Markup.Primitives { ////// An implementation of MarkupObject for DependencyObjects that works also for CLR only objects /// internal class ElementMarkupObject : MarkupObject { internal ElementMarkupObject(object instance, XamlDesignerSerializationManager manager) { Debug.Assert(instance != null); _instance = instance; _context = new ElementObjectContext(this, null); _manager = manager; } public override Type ObjectType { get { return _instance.GetType(); } } public override object Instance { get { return _instance; } } internal override IEnumerableGetProperties(bool mapToConstructorArgs) { ValueSerializer valueSerializer = ValueSerializer.GetSerializerFor(ObjectType, Context); if (valueSerializer != null && valueSerializer.CanConvertToString(_instance, Context)) { yield return new ElementStringValueProperty(this); if (_key != null) { yield return _key; } } else { Dictionary constructorArguments = null; // if this markup item is the value of property in attribute form and the instance // it represents is a MarkupExtension, then we return any properties that are // constructor arguments as ElementConstructorArgument markup properties if (mapToConstructorArgs && _instance is MarkupExtension) { // Detect if the instance should be constructed using constructor parameters by // seeing if it can be converted to an instance descriptor that uses a constructor. TypeConverter converter = TypeDescriptor.GetConverter(_instance); if (converter != null && converter.CanConvertTo(Context, typeof(InstanceDescriptor))) { InstanceDescriptor instanceDescriptor; try { instanceDescriptor = converter.ConvertTo(_context, TypeConverterHelper.InvariantEnglishUS, _instance, typeof(InstanceDescriptor)) as InstanceDescriptor; } catch (InvalidOperationException) { // If we get this just ignore the converter instanceDescriptor = null; } catch (NotSupportedException) { // If we get this just ignore the converter instanceDescriptor = null; } if (instanceDescriptor != null) { ConstructorInfo ctorInfo = instanceDescriptor.MemberInfo as ConstructorInfo; if (ctorInfo != null) { ParameterInfo[] parameters = ctorInfo.GetParameters(); if (parameters != null && parameters.Length == instanceDescriptor.Arguments.Count) { int i = 0; foreach (object value in instanceDescriptor.Arguments) { if (constructorArguments == null) { constructorArguments = new Dictionary (); } // store a list of the parameters that are constructor arguments // so that we don't return those properties again constructorArguments.Add(parameters[i].Name, parameters[i].Name); yield return new ElementConstructorArgument(value, parameters[i++].ParameterType, this); } } } } } } foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(_instance)) { DesignerSerializationVisibility visibility = descriptor.SerializationVisibility; if (visibility != DesignerSerializationVisibility.Hidden && (!descriptor.IsReadOnly || visibility == DesignerSerializationVisibility.Content) && ShouldSerialize(descriptor, _instance, _manager)) { if (visibility == DesignerSerializationVisibility.Content) { // Ensure the collection has content object value = descriptor.GetValue(_instance); if (value == null) { continue; } else { ICollection collection = value as ICollection; if (collection != null && collection.Count < 1) { continue; } IEnumerable enumerable = value as IEnumerable; if (enumerable != null && !enumerable.GetEnumerator().MoveNext()) { continue; } } } if (constructorArguments != null) { ConstructorArgumentAttribute constructorArgumentAttribute = descriptor.Attributes[typeof(ConstructorArgumentAttribute)] as ConstructorArgumentAttribute; if (constructorArgumentAttribute != null && constructorArguments.ContainsKey(constructorArgumentAttribute.ArgumentName)) { // Skip this property, it has already been represented by a constructor parameter continue; } } yield return new ElementProperty(this, descriptor); } } IDictionary dictionary = _instance as IDictionary; if (dictionary != null) { yield return new ElementDictionaryItemsPseudoProperty(dictionary, typeof(IDictionary), this); } else { IEnumerable enumerable = _instance as IEnumerable; if (enumerable != null && enumerable.GetEnumerator().MoveNext()) { yield return new ElementItemsPseudoProperty(enumerable, typeof(IEnumerable), this); } } if (_key != null) { yield return _key; } } } public override AttributeCollection Attributes { get { return TypeDescriptor.GetAttributes(ObjectType); } } public override void AssignRootContext(IValueSerializerContext context) { _context = new ElementObjectContext(this, context); } internal IValueSerializerContext Context { get { return _context; } } internal XamlDesignerSerializationManager Manager { get { return _manager; } } internal void SetKey(ElementKey key) { _key = key; } private sealed class ElementObjectContext : ValueSerializerContextWrapper, IValueSerializerContext { ElementMarkupObject _object; public ElementObjectContext(ElementMarkupObject obj, IValueSerializerContext baseContext): base(baseContext) { _object = obj; } object ITypeDescriptorContext.Instance { get { return _object.Instance; } } } private static bool ShouldSerialize(PropertyDescriptor pd, object instance, XamlDesignerSerializationManager manager) { MethodInfo shouldSerializeMethod; object invokeInstance = instance; DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(pd); if (dpd != null && dpd.IsAttached) { Type ownerType = dpd.DependencyProperty.OwnerType; string propertyName = dpd.DependencyProperty.Name; string keyName = propertyName + "!"; if (!TryGetShouldSerializeMethod(new ShouldSerializeKey(ownerType, keyName), out shouldSerializeMethod)) { string methodName = "ShouldSerialize" + propertyName; shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObject, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsManager, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsMode, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObjectManager, null); if (shouldSerializeMethod != null && shouldSerializeMethod.ReturnType != typeof(bool)) shouldSerializeMethod = null; CacheShouldSerializeMethod(new ShouldSerializeKey(ownerType, keyName), shouldSerializeMethod); } invokeInstance = null; // static method } else { if (!TryGetShouldSerializeMethod(new ShouldSerializeKey(instance.GetType(), pd.Name), out shouldSerializeMethod)) { Type instanceType = instance.GetType(); string methodName = "ShouldSerialize" + pd.Name; shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObject, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsManager, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsMode, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObjectManager, null); if (shouldSerializeMethod != null && shouldSerializeMethod.ReturnType != typeof(bool)) shouldSerializeMethod = null; CacheShouldSerializeMethod(new ShouldSerializeKey(instanceType, pd.Name), shouldSerializeMethod); } } if (shouldSerializeMethod != null) { ParameterInfo[] parameters = shouldSerializeMethod.GetParameters(); if (parameters != null) { object[] args; if (parameters.Length == 1) { if (parameters[0].ParameterType == typeof(DependencyObject)) { args = new object[] { instance as DependencyObject }; } else if (parameters[0].ParameterType == typeof(XamlWriterMode)) { args = new object[] { manager.XamlWriterMode }; } else { args = new object[] { manager }; } } else args = new object[] { instance as DependencyObject, manager }; return (bool)shouldSerializeMethod.Invoke(invokeInstance, args); } } return pd.ShouldSerializeValue(instance); } private struct ShouldSerializeKey { public ShouldSerializeKey(Type type, string propertyName) { _type = type; _propertyName = propertyName; } public override bool Equals(object obj) { if (!(obj is ShouldSerializeKey)) return false; ShouldSerializeKey other = (ShouldSerializeKey)obj; return other._type == _type && other._propertyName == _propertyName; } /// /// Forward to .Equals /// public static bool operator ==(ShouldSerializeKey key1, ShouldSerializeKey key2) { return key1.Equals(key2); } ////// Forward to .Equals /// public static bool operator !=(ShouldSerializeKey key1, ShouldSerializeKey key2) { return !(key1.Equals(key2)); } public override int GetHashCode() { return _type.GetHashCode() ^ _propertyName.GetHashCode(); } private Type _type; private string _propertyName; } private static bool TryGetShouldSerializeMethod(ShouldSerializeKey key, out MethodInfo methodInfo) { object value = _shouldSerializeCache[key]; if (value == null || value == _shouldSerializeCacheLock) { // The _shouldSerializeCacheLock is used as a sentinal for null methodInfo = null; return value != null; } else { methodInfo = value as MethodInfo; return true; } } private static void CacheShouldSerializeMethod(ShouldSerializeKey key, MethodInfo methodInfo) { // The instance stored in _shouldSerializeCacheLock is used as a sentinal for null // The avoids having to perform two lookups in the Hashtable to detect a cached null value. object value = methodInfo == null ? _shouldSerializeCacheLock : methodInfo; lock (_shouldSerializeCacheLock) { _shouldSerializeCache[key] = value; } } private static object _shouldSerializeCacheLock = new object(); private static Hashtable _shouldSerializeCache = new Hashtable(); private static Type[] _shouldSerializeArgsObject = new Type[] { typeof(DependencyObject) }; private static Type[] _shouldSerializeArgsManager = new Type[] { typeof(XamlDesignerSerializationManager) }; private static Type[] _shouldSerializeArgsMode = new Type[] { typeof(XamlWriterMode) }; private static Type[] _shouldSerializeArgsObjectManager = new Type[] { typeof(DependencyObject), typeof(XamlDesignerSerializationManager) }; private static Attribute[] _propertyAttributes = new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.SetValues) }; private object _instance; private IValueSerializerContext _context; private ElementKey _key; private XamlDesignerSerializationManager _manager; } internal abstract class ElementPropertyBase : MarkupProperty { public ElementPropertyBase(XamlDesignerSerializationManager manager) { _manager = manager; } public override bool IsComposite { get { if (!_isCompositeCalculated) { _isCompositeCalculated = true; object value = Value; if (value == null) { _isComposite = true; } else if (value is string && PropertyType.IsAssignableFrom(typeof(object))) { _isComposite = false; } else if (value is MarkupExtension) { _isComposite = true; } else { _isComposite = !CanConvertToString(value); } } return _isComposite; } } public override string StringValue { get { if (IsComposite) { return String.Empty; } object value = Value; string stringValue = value as string; if (stringValue != null) { return stringValue; } ValueSerializer serializer = GetValueSerializer(); if (serializer == null) { return String.Empty; } return serializer.ConvertToString(value, Context); } } public override IEnumerableItems { get { object value = Value; if (value != null) { if (PropertyDescriptor != null && (PropertyDescriptor.IsReadOnly || (!PropertyIsAttached(PropertyDescriptor) && PropertyType == value.GetType() && // These types the serializer will synthesize a start element when // reading them in (typeof(IList).IsAssignableFrom(PropertyType) || typeof(IDictionary).IsAssignableFrom(PropertyType) || typeof(Freezable).IsAssignableFrom(PropertyType) || typeof(FrameworkElementFactory).IsAssignableFrom(PropertyType))) && HasNoSerializableProperties(value) && !IsEmpty(value))) { IDictionary dictionary = value as IDictionary; if (dictionary != null) { Type keyType = GetDictionaryKeyType(dictionary); // Attempt to emit the contents of the dictionary in a more deterministic // order. This is not guarenteed to be deterministic because it uses ToString // which is not guarenteed to be unique for each value. Keys with non-unique // ToString() values will not be emitted deterministically. DictionaryEntry[] entries = new DictionaryEntry[dictionary.Count]; dictionary.CopyTo(entries, 0); Array.Sort(entries, delegate(DictionaryEntry one, DictionaryEntry two) { return String.Compare(one.Key.ToString(), two.Key.ToString()); }); foreach (DictionaryEntry entry in entries) { ElementMarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), entry.Value, Context, false), Manager); subItem.SetKey(new ElementKey(entry.Key, keyType, subItem)); yield return subItem; } } else { IEnumerable items = value as IEnumerable; if (items != null) { foreach (object o in items) { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), o, Context, false), Manager); yield return subItem; } } else { if (PropertyType == typeof(FrameworkElementFactory) && value is FrameworkElementFactory) { MarkupObject subItem = new FrameworkElementFactoryMarkupObject(value as FrameworkElementFactory, Manager); yield return subItem; } else { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), value, Context, true), Manager); yield return subItem; } } } } else { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), value, Context, true), Manager); yield return subItem; } } else { MarkupObject subItem = new ElementMarkupObject(new System.Windows.Markup.NullExtension(), Manager); yield return subItem; } } } private bool PropertyIsAttached(PropertyDescriptor descriptor) { DependencyPropertyDescriptor dependencyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(PropertyDescriptor); return dependencyPropertyDescriptor != null && dependencyPropertyDescriptor.IsAttached; } private bool HasNoSerializableProperties(object value) { if (value is FrameworkElementFactory) return true; ElementMarkupObject item = new ElementMarkupObject(value, Manager); foreach (MarkupProperty property in item.Properties) { if (!property.IsContent) { return false; } } return true; } private bool IsEmpty(object value) { IEnumerable collection = value as IEnumerable; if (collection != null) { foreach (object o in collection) return false; return true; } return false; } protected IValueSerializerContext Context { get { if (_context == null) { _context = new ElementPropertyContext(this, GetItemContext()); } return _context; } } internal XamlDesignerSerializationManager Manager { get { return _manager; } } static readonly List EmptyTypes = new List (); public override IEnumerable TypeReferences { get { ValueSerializer serializer = GetValueSerializer(); if (serializer == null) return EmptyTypes; else return serializer.TypeReferences(Value, Context); } } protected bool CanConvertToString( object value ) { // See if this value can be converted to a string by a value serializer or type converter if( value == null ) { return false; } ValueSerializer serializer = GetValueSerializer(); return serializer != null && serializer.CanConvertToString(value, Context); } protected abstract IValueSerializerContext GetItemContext(); protected abstract Type GetObjectType(); private sealed class ElementPropertyContext : ValueSerializerContextWrapper, IValueSerializerContext { ElementPropertyBase _property; public ElementPropertyContext(ElementPropertyBase property, IValueSerializerContext baseContext) : base(baseContext) { _property = property; } PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor { get { return _property.PropertyDescriptor; } } } private ValueSerializer GetValueSerializer() { PropertyDescriptor descriptor = this.PropertyDescriptor; if (descriptor == null) { DependencyProperty property = this.DependencyProperty; if (property != null) descriptor = DependencyPropertyDescriptor.FromProperty(property, GetObjectType()); } if (descriptor != null) return ValueSerializer.GetSerializerFor(descriptor, GetItemContext()); else return ValueSerializer.GetSerializerFor(PropertyType, GetItemContext()); } private static Dictionary _keyTypeMap; private static Type GetDictionaryKeyType(IDictionary value) { Type type = value.GetType(); Type result; if (_keyTypeMap == null) _keyTypeMap = new Dictionary (); if (!_keyTypeMap.TryGetValue(type, out result)) { foreach (Type interfaceType in type.GetInterfaces()) { if (interfaceType.IsGenericType) { Type genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(System.Collections.Generic.IDictionary<,>)) return interfaceType.GetGenericArguments()[0]; } } result = typeof(object); _keyTypeMap[type] = result; } return result; } private bool _isComposite; private bool _isCompositeCalculated; private IValueSerializerContext _context; private XamlDesignerSerializationManager _manager; } internal abstract class ElementObjectPropertyBase : ElementPropertyBase { protected ElementObjectPropertyBase(ElementMarkupObject obj): base(obj.Manager) { Debug.Assert(obj != null); _object = obj; } protected override IValueSerializerContext GetItemContext() { return _object.Context; } protected override Type GetObjectType() { return _object.ObjectType; } protected readonly ElementMarkupObject _object; } /// /// An implementation of MarkupProperty for DependencyObjects that works also for CLR only objects /// internal class ElementProperty : ElementObjectPropertyBase { internal ElementProperty(ElementMarkupObject obj, PropertyDescriptor descriptor) : base(obj) { Debug.Assert(descriptor != null); _descriptor = descriptor; } public override string Name { get { return _descriptor.Name; } } public override Type PropertyType { get { return _descriptor.PropertyType; } } public override PropertyDescriptor PropertyDescriptor { get { return _descriptor; } } public override bool IsAttached { get { UpdateDependencyProperty(); return _isAttached; } } public override DependencyProperty DependencyProperty { get { UpdateDependencyProperty(); return _dependencyProperty; } } public override object Value { get { object value; DependencyProperty DP = DependencyProperty; // For DPs, we use ReadLocalValue to find the property, and handle // unset values. if (DP != null) { DependencyObject DO = _object.Instance as DependencyObject; Debug.Assert(DO != null); // get the local value of the DP value = DO.ReadLocalValue(DP); // Expressions require special handling Expression expression = value as Expression; if (expression != null) { // Special-case: Expressions always get converted to an ME if // possible (and requested), and get de-referenced otherwise. TypeConverter converter = TypeDescriptor.GetConverter(value); if (Manager.XamlWriterMode == XamlWriterMode.Expression && converter.CanConvertTo(typeof(MarkupExtension))) { value = converter.ConvertTo(expression, typeof(MarkupExtension)); } else { value = expression.GetValue(DO, DP); } } // If the expression gave us UnsetValue, fall back to the default. if (value == DependencyProperty.UnsetValue) { value = DP.GetDefaultValue(DO.DependencyObjectType); } } // If this is the VisualTree property of a template, we have to do special processing. // Long-term plan is to replace this with an attribute on the type, that tells us how // to serialize its content. else if ((Name == "Template" || Name == "VisualTree") && Context.Instance is FrameworkTemplate && (Context.Instance as FrameworkTemplate).HasContent ) { // Instantiate the template, in un-optimized form. This makes the template content // load as if it were loaded from xaml outside a template. The only exception is that // TemplateBinding's will show up as a TemplateBindingExtension. value = (Context.Instance as FrameworkTemplate).LoadContent(); } // Otherwise, get the value from the property descriptor. else { value = _descriptor.GetValue(_object.Instance); } // Convert the resulting value from above into a MarkupExtension, if necessary/possible, // but only if there is no value serializer; if the type supports conversion to both // string and ME, we give preference to the string conversion. if( !(value is MarkupExtension) && !CanConvertToString(value) ) { value = CheckForMarkupExtension(PropertyType, value, Context, true); } return value; } } public override AttributeCollection Attributes { get { return _descriptor.Attributes; } } private void UpdateDependencyProperty() { if (!_isDependencyPropertyCached) { DependencyPropertyDescriptor dpDesc = DependencyPropertyDescriptor.FromProperty(_descriptor); if (dpDesc != null) { _dependencyProperty = dpDesc.DependencyProperty; _isAttached = dpDesc.IsAttached; } _isDependencyPropertyCached = true; } } // // Check for values that can be converted into markup extensions, either because // they are a well known type ((null, arrays, enums, and types), or because they // can be type converted into an ME. // internal static object CheckForMarkupExtension( Type propertyType, object value, IValueSerializerContext context, bool convertEnums) { // null => NullExtension if (value == null) { return new NullExtension(); } // See if the type has a type converter that can create a MarkupExtension // (Have to do this after the null check so that GetConverter doesn't get // an invalid argument.) TypeConverter converter = TypeDescriptor.GetConverter(value); if (converter.CanConvertTo(context, typeof(MarkupExtension))) { // The type provides a converter that creates a MarkupExtension. return converter.ConvertTo(context, TypeConverterHelper.InvariantEnglishUS, value, typeof(MarkupExtension)); } // System.Type => TypeExtension Type type = value as Type; if (type != null) { // If the property is declared to be a type already, we don't need to convert it // into {x:Type} syntax. if( propertyType == typeof(Type) ) { return value; } return new TypeExtension(type); } // Enums => StaticExtension if (convertEnums) { Enum enumValue = value as Enum; if (enumValue != null) { ValueSerializer typeSerializer = context.GetValueSerializerFor(typeof(Type)); Debug.Assert(typeSerializer != null, "typeSerializer for Enum was null"); string typeName = typeSerializer.ConvertToString(enumValue.GetType(), context); return new StaticExtension(typeName + "." + enumValue.ToString()); } } // Arrays => ArrayExtension Array array = value as Array; if (array != null) { return new ArrayExtension(array); } // Otherwise, value is unchanged. return value; } private PropertyDescriptor _descriptor; private bool _isDependencyPropertyCached; private DependencyProperty _dependencyProperty; private bool _isAttached; } ////// Pseudo-property for strings passed to a type converter /// internal class ElementStringValueProperty : MarkupProperty { internal ElementStringValueProperty(ElementMarkupObject obj) { _object = obj; } public override string Name { get { return "StringValue"; } } public override Type PropertyType { get { return typeof(string); } } public override bool IsValueAsString { get { return true; } } public override object Value { get { return StringValue; } } public override string StringValue { get { ValueSerializer serializer = ValueSerializer.GetSerializerFor(_object.ObjectType, _object.Context); Debug.Assert(serializer != null && serializer.CanConvertToString(_object.Instance, _object.Context), "StringValue property value created for a type that cannot be converted to string"); return serializer.ConvertToString(_object.Instance, _object.Context); } } public override IEnumerableItems { get { Debug.WriteLine("ElementMarkupObject.Items is not implemented"); return null; } } public override AttributeCollection Attributes { get { return AttributeCollection.Empty; } } public override IEnumerable TypeReferences { get { ValueSerializer serializer = ValueSerializer.GetSerializerFor(_object.ObjectType, _object.Context); Debug.Assert(serializer != null && serializer.CanConvertToString(_object.Instance, _object.Context), "StringValue property value created for a type that cannot be converted to string"); return serializer.TypeReferences(_object.Instance, _object.Context); } } private ElementMarkupObject _object; } /// /// Pseudo-property for the key of a dictionary element /// internal abstract class ElementPseudoPropertyBase : ElementObjectPropertyBase { internal ElementPseudoPropertyBase(object value, Type type, ElementMarkupObject obj) : base(obj) { _value = value; _type = type; } public override Type PropertyType { get { return _type; } } public override object Value { get { return ElementProperty.CheckForMarkupExtension(PropertyType, _value, Context, true /*convertEnums*/); } } public override AttributeCollection Attributes { get { return AttributeCollection.Empty; } } public override IEnumerableTypeReferences { get { return new Type[0]; } } private object _value; private Type _type; } /// /// Pseudo-property for the key of a dictionary element /// internal class ElementKey : ElementPseudoPropertyBase { internal ElementKey(object value, Type type, ElementMarkupObject obj) : base(value, type, obj) { } public override string Name { get { return "Key"; } } public override bool IsKey { get { return true; } } } ////// Pseudo-property for constructor arguments /// internal class ElementConstructorArgument : ElementPseudoPropertyBase { internal ElementConstructorArgument(object value, Type type, ElementMarkupObject obj) : base(value, type, obj) { } public override string Name { get { return "Argument"; } } public override bool IsConstructorArgument { get { return true; } } } ////// Pseudo-property for IEnumerable implementations /// internal class ElementItemsPseudoProperty : ElementPseudoPropertyBase { internal ElementItemsPseudoProperty(IEnumerable value, Type type, ElementMarkupObject obj) : base(value, type, obj) { _value = value; } public override string Name { get { return "Items"; } } public override bool IsContent { get { return true; } } public override bool IsComposite { get { return true; } } public override IEnumerableItems { get { foreach (object instance in _value) { yield return new ElementMarkupObject(instance, Manager); } } } IEnumerable _value; } /// /// Pseudo-property for IDictionary implementation /// internal class ElementDictionaryItemsPseudoProperty : ElementPseudoPropertyBase { internal ElementDictionaryItemsPseudoProperty(IDictionary value, Type type, ElementMarkupObject obj) : base(value, type, obj) { _value = value; } public override string Name { get { return "Entries"; } } public override bool IsContent { get { return true; } } public override bool IsComposite { get { return true; } } public override IEnumerableItems { get { foreach (DictionaryEntry entry in _value) { ElementMarkupObject item = new ElementMarkupObject(entry.Value, Manager); item.SetKey(new ElementKey(entry.Key, typeof(object), item)); yield return item; } } } IDictionary _value; } internal class ValueSerializerContextWrapper : IValueSerializerContext { IValueSerializerContext _baseContext; public ValueSerializerContextWrapper(IValueSerializerContext baseContext) { _baseContext = baseContext; } public ValueSerializer GetValueSerializerFor(PropertyDescriptor descriptor) { if (_baseContext != null) return _baseContext.GetValueSerializerFor(descriptor); else return null; } public ValueSerializer GetValueSerializerFor(Type type) { if (_baseContext != null) return _baseContext.GetValueSerializerFor(type); else return null; } public IContainer Container { get { if (_baseContext != null) return _baseContext.Container; else return null; } } public object Instance { get { if (_baseContext != null) return _baseContext.Instance; else return null; } } public void OnComponentChanged() { if (_baseContext != null) _baseContext.OnComponentChanged(); } public bool OnComponentChanging() { if (_baseContext != null) return _baseContext.OnComponentChanging(); else return true; } public PropertyDescriptor PropertyDescriptor { get { if (_baseContext != null) return _baseContext.PropertyDescriptor; else return null; } } public object GetService(Type serviceType) { if (_baseContext != null) return _baseContext.GetService(serviceType); else return null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ElementMarkupObject.cs // // Contents: MarkupObject and MarkupProperty implementation for // DependencyObject // // Created: 04/28/2005 [....] // // // Class hierarchy in this file: // // (MarkupObject) // ElementMarkupObject // // (MarkupProperty) // ElementPropertyBase // ElementObjectPropertyBase // ElementProperty // ElementPseudoPropertyBase // ElementKey // ElementConstructorArgument // ElementItemsPseudoProperty // ElementDictionaryItemsPseudoProperty // ElementStringValueProperty // //----------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Text; using System.Windows; using System.Windows.Data; using System.Windows.Markup; using System.Windows.Documents; namespace System.Windows.Markup.Primitives { /// /// An implementation of MarkupObject for DependencyObjects that works also for CLR only objects /// internal class ElementMarkupObject : MarkupObject { internal ElementMarkupObject(object instance, XamlDesignerSerializationManager manager) { Debug.Assert(instance != null); _instance = instance; _context = new ElementObjectContext(this, null); _manager = manager; } public override Type ObjectType { get { return _instance.GetType(); } } public override object Instance { get { return _instance; } } internal override IEnumerableGetProperties(bool mapToConstructorArgs) { ValueSerializer valueSerializer = ValueSerializer.GetSerializerFor(ObjectType, Context); if (valueSerializer != null && valueSerializer.CanConvertToString(_instance, Context)) { yield return new ElementStringValueProperty(this); if (_key != null) { yield return _key; } } else { Dictionary constructorArguments = null; // if this markup item is the value of property in attribute form and the instance // it represents is a MarkupExtension, then we return any properties that are // constructor arguments as ElementConstructorArgument markup properties if (mapToConstructorArgs && _instance is MarkupExtension) { // Detect if the instance should be constructed using constructor parameters by // seeing if it can be converted to an instance descriptor that uses a constructor. TypeConverter converter = TypeDescriptor.GetConverter(_instance); if (converter != null && converter.CanConvertTo(Context, typeof(InstanceDescriptor))) { InstanceDescriptor instanceDescriptor; try { instanceDescriptor = converter.ConvertTo(_context, TypeConverterHelper.InvariantEnglishUS, _instance, typeof(InstanceDescriptor)) as InstanceDescriptor; } catch (InvalidOperationException) { // If we get this just ignore the converter instanceDescriptor = null; } catch (NotSupportedException) { // If we get this just ignore the converter instanceDescriptor = null; } if (instanceDescriptor != null) { ConstructorInfo ctorInfo = instanceDescriptor.MemberInfo as ConstructorInfo; if (ctorInfo != null) { ParameterInfo[] parameters = ctorInfo.GetParameters(); if (parameters != null && parameters.Length == instanceDescriptor.Arguments.Count) { int i = 0; foreach (object value in instanceDescriptor.Arguments) { if (constructorArguments == null) { constructorArguments = new Dictionary (); } // store a list of the parameters that are constructor arguments // so that we don't return those properties again constructorArguments.Add(parameters[i].Name, parameters[i].Name); yield return new ElementConstructorArgument(value, parameters[i++].ParameterType, this); } } } } } } foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(_instance)) { DesignerSerializationVisibility visibility = descriptor.SerializationVisibility; if (visibility != DesignerSerializationVisibility.Hidden && (!descriptor.IsReadOnly || visibility == DesignerSerializationVisibility.Content) && ShouldSerialize(descriptor, _instance, _manager)) { if (visibility == DesignerSerializationVisibility.Content) { // Ensure the collection has content object value = descriptor.GetValue(_instance); if (value == null) { continue; } else { ICollection collection = value as ICollection; if (collection != null && collection.Count < 1) { continue; } IEnumerable enumerable = value as IEnumerable; if (enumerable != null && !enumerable.GetEnumerator().MoveNext()) { continue; } } } if (constructorArguments != null) { ConstructorArgumentAttribute constructorArgumentAttribute = descriptor.Attributes[typeof(ConstructorArgumentAttribute)] as ConstructorArgumentAttribute; if (constructorArgumentAttribute != null && constructorArguments.ContainsKey(constructorArgumentAttribute.ArgumentName)) { // Skip this property, it has already been represented by a constructor parameter continue; } } yield return new ElementProperty(this, descriptor); } } IDictionary dictionary = _instance as IDictionary; if (dictionary != null) { yield return new ElementDictionaryItemsPseudoProperty(dictionary, typeof(IDictionary), this); } else { IEnumerable enumerable = _instance as IEnumerable; if (enumerable != null && enumerable.GetEnumerator().MoveNext()) { yield return new ElementItemsPseudoProperty(enumerable, typeof(IEnumerable), this); } } if (_key != null) { yield return _key; } } } public override AttributeCollection Attributes { get { return TypeDescriptor.GetAttributes(ObjectType); } } public override void AssignRootContext(IValueSerializerContext context) { _context = new ElementObjectContext(this, context); } internal IValueSerializerContext Context { get { return _context; } } internal XamlDesignerSerializationManager Manager { get { return _manager; } } internal void SetKey(ElementKey key) { _key = key; } private sealed class ElementObjectContext : ValueSerializerContextWrapper, IValueSerializerContext { ElementMarkupObject _object; public ElementObjectContext(ElementMarkupObject obj, IValueSerializerContext baseContext): base(baseContext) { _object = obj; } object ITypeDescriptorContext.Instance { get { return _object.Instance; } } } private static bool ShouldSerialize(PropertyDescriptor pd, object instance, XamlDesignerSerializationManager manager) { MethodInfo shouldSerializeMethod; object invokeInstance = instance; DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(pd); if (dpd != null && dpd.IsAttached) { Type ownerType = dpd.DependencyProperty.OwnerType; string propertyName = dpd.DependencyProperty.Name; string keyName = propertyName + "!"; if (!TryGetShouldSerializeMethod(new ShouldSerializeKey(ownerType, keyName), out shouldSerializeMethod)) { string methodName = "ShouldSerialize" + propertyName; shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObject, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsManager, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsMode, null); if (shouldSerializeMethod == null) shouldSerializeMethod = ownerType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObjectManager, null); if (shouldSerializeMethod != null && shouldSerializeMethod.ReturnType != typeof(bool)) shouldSerializeMethod = null; CacheShouldSerializeMethod(new ShouldSerializeKey(ownerType, keyName), shouldSerializeMethod); } invokeInstance = null; // static method } else { if (!TryGetShouldSerializeMethod(new ShouldSerializeKey(instance.GetType(), pd.Name), out shouldSerializeMethod)) { Type instanceType = instance.GetType(); string methodName = "ShouldSerialize" + pd.Name; shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObject, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsManager, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsMode, null); if (shouldSerializeMethod == null) shouldSerializeMethod = instanceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, _shouldSerializeArgsObjectManager, null); if (shouldSerializeMethod != null && shouldSerializeMethod.ReturnType != typeof(bool)) shouldSerializeMethod = null; CacheShouldSerializeMethod(new ShouldSerializeKey(instanceType, pd.Name), shouldSerializeMethod); } } if (shouldSerializeMethod != null) { ParameterInfo[] parameters = shouldSerializeMethod.GetParameters(); if (parameters != null) { object[] args; if (parameters.Length == 1) { if (parameters[0].ParameterType == typeof(DependencyObject)) { args = new object[] { instance as DependencyObject }; } else if (parameters[0].ParameterType == typeof(XamlWriterMode)) { args = new object[] { manager.XamlWriterMode }; } else { args = new object[] { manager }; } } else args = new object[] { instance as DependencyObject, manager }; return (bool)shouldSerializeMethod.Invoke(invokeInstance, args); } } return pd.ShouldSerializeValue(instance); } private struct ShouldSerializeKey { public ShouldSerializeKey(Type type, string propertyName) { _type = type; _propertyName = propertyName; } public override bool Equals(object obj) { if (!(obj is ShouldSerializeKey)) return false; ShouldSerializeKey other = (ShouldSerializeKey)obj; return other._type == _type && other._propertyName == _propertyName; } /// /// Forward to .Equals /// public static bool operator ==(ShouldSerializeKey key1, ShouldSerializeKey key2) { return key1.Equals(key2); } ////// Forward to .Equals /// public static bool operator !=(ShouldSerializeKey key1, ShouldSerializeKey key2) { return !(key1.Equals(key2)); } public override int GetHashCode() { return _type.GetHashCode() ^ _propertyName.GetHashCode(); } private Type _type; private string _propertyName; } private static bool TryGetShouldSerializeMethod(ShouldSerializeKey key, out MethodInfo methodInfo) { object value = _shouldSerializeCache[key]; if (value == null || value == _shouldSerializeCacheLock) { // The _shouldSerializeCacheLock is used as a sentinal for null methodInfo = null; return value != null; } else { methodInfo = value as MethodInfo; return true; } } private static void CacheShouldSerializeMethod(ShouldSerializeKey key, MethodInfo methodInfo) { // The instance stored in _shouldSerializeCacheLock is used as a sentinal for null // The avoids having to perform two lookups in the Hashtable to detect a cached null value. object value = methodInfo == null ? _shouldSerializeCacheLock : methodInfo; lock (_shouldSerializeCacheLock) { _shouldSerializeCache[key] = value; } } private static object _shouldSerializeCacheLock = new object(); private static Hashtable _shouldSerializeCache = new Hashtable(); private static Type[] _shouldSerializeArgsObject = new Type[] { typeof(DependencyObject) }; private static Type[] _shouldSerializeArgsManager = new Type[] { typeof(XamlDesignerSerializationManager) }; private static Type[] _shouldSerializeArgsMode = new Type[] { typeof(XamlWriterMode) }; private static Type[] _shouldSerializeArgsObjectManager = new Type[] { typeof(DependencyObject), typeof(XamlDesignerSerializationManager) }; private static Attribute[] _propertyAttributes = new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.SetValues) }; private object _instance; private IValueSerializerContext _context; private ElementKey _key; private XamlDesignerSerializationManager _manager; } internal abstract class ElementPropertyBase : MarkupProperty { public ElementPropertyBase(XamlDesignerSerializationManager manager) { _manager = manager; } public override bool IsComposite { get { if (!_isCompositeCalculated) { _isCompositeCalculated = true; object value = Value; if (value == null) { _isComposite = true; } else if (value is string && PropertyType.IsAssignableFrom(typeof(object))) { _isComposite = false; } else if (value is MarkupExtension) { _isComposite = true; } else { _isComposite = !CanConvertToString(value); } } return _isComposite; } } public override string StringValue { get { if (IsComposite) { return String.Empty; } object value = Value; string stringValue = value as string; if (stringValue != null) { return stringValue; } ValueSerializer serializer = GetValueSerializer(); if (serializer == null) { return String.Empty; } return serializer.ConvertToString(value, Context); } } public override IEnumerableItems { get { object value = Value; if (value != null) { if (PropertyDescriptor != null && (PropertyDescriptor.IsReadOnly || (!PropertyIsAttached(PropertyDescriptor) && PropertyType == value.GetType() && // These types the serializer will synthesize a start element when // reading them in (typeof(IList).IsAssignableFrom(PropertyType) || typeof(IDictionary).IsAssignableFrom(PropertyType) || typeof(Freezable).IsAssignableFrom(PropertyType) || typeof(FrameworkElementFactory).IsAssignableFrom(PropertyType))) && HasNoSerializableProperties(value) && !IsEmpty(value))) { IDictionary dictionary = value as IDictionary; if (dictionary != null) { Type keyType = GetDictionaryKeyType(dictionary); // Attempt to emit the contents of the dictionary in a more deterministic // order. This is not guarenteed to be deterministic because it uses ToString // which is not guarenteed to be unique for each value. Keys with non-unique // ToString() values will not be emitted deterministically. DictionaryEntry[] entries = new DictionaryEntry[dictionary.Count]; dictionary.CopyTo(entries, 0); Array.Sort(entries, delegate(DictionaryEntry one, DictionaryEntry two) { return String.Compare(one.Key.ToString(), two.Key.ToString()); }); foreach (DictionaryEntry entry in entries) { ElementMarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), entry.Value, Context, false), Manager); subItem.SetKey(new ElementKey(entry.Key, keyType, subItem)); yield return subItem; } } else { IEnumerable items = value as IEnumerable; if (items != null) { foreach (object o in items) { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), o, Context, false), Manager); yield return subItem; } } else { if (PropertyType == typeof(FrameworkElementFactory) && value is FrameworkElementFactory) { MarkupObject subItem = new FrameworkElementFactoryMarkupObject(value as FrameworkElementFactory, Manager); yield return subItem; } else { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), value, Context, true), Manager); yield return subItem; } } } } else { MarkupObject subItem = new ElementMarkupObject( ElementProperty.CheckForMarkupExtension(typeof(Object), value, Context, true), Manager); yield return subItem; } } else { MarkupObject subItem = new ElementMarkupObject(new System.Windows.Markup.NullExtension(), Manager); yield return subItem; } } } private bool PropertyIsAttached(PropertyDescriptor descriptor) { DependencyPropertyDescriptor dependencyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(PropertyDescriptor); return dependencyPropertyDescriptor != null && dependencyPropertyDescriptor.IsAttached; } private bool HasNoSerializableProperties(object value) { if (value is FrameworkElementFactory) return true; ElementMarkupObject item = new ElementMarkupObject(value, Manager); foreach (MarkupProperty property in item.Properties) { if (!property.IsContent) { return false; } } return true; } private bool IsEmpty(object value) { IEnumerable collection = value as IEnumerable; if (collection != null) { foreach (object o in collection) return false; return true; } return false; } protected IValueSerializerContext Context { get { if (_context == null) { _context = new ElementPropertyContext(this, GetItemContext()); } return _context; } } internal XamlDesignerSerializationManager Manager { get { return _manager; } } static readonly List EmptyTypes = new List (); public override IEnumerable TypeReferences { get { ValueSerializer serializer = GetValueSerializer(); if (serializer == null) return EmptyTypes; else return serializer.TypeReferences(Value, Context); } } protected bool CanConvertToString( object value ) { // See if this value can be converted to a string by a value serializer or type converter if( value == null ) { return false; } ValueSerializer serializer = GetValueSerializer(); return serializer != null && serializer.CanConvertToString(value, Context); } protected abstract IValueSerializerContext GetItemContext(); protected abstract Type GetObjectType(); private sealed class ElementPropertyContext : ValueSerializerContextWrapper, IValueSerializerContext { ElementPropertyBase _property; public ElementPropertyContext(ElementPropertyBase property, IValueSerializerContext baseContext) : base(baseContext) { _property = property; } PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor { get { return _property.PropertyDescriptor; } } } private ValueSerializer GetValueSerializer() { PropertyDescriptor descriptor = this.PropertyDescriptor; if (descriptor == null) { DependencyProperty property = this.DependencyProperty; if (property != null) descriptor = DependencyPropertyDescriptor.FromProperty(property, GetObjectType()); } if (descriptor != null) return ValueSerializer.GetSerializerFor(descriptor, GetItemContext()); else return ValueSerializer.GetSerializerFor(PropertyType, GetItemContext()); } private static Dictionary _keyTypeMap; private static Type GetDictionaryKeyType(IDictionary value) { Type type = value.GetType(); Type result; if (_keyTypeMap == null) _keyTypeMap = new Dictionary (); if (!_keyTypeMap.TryGetValue(type, out result)) { foreach (Type interfaceType in type.GetInterfaces()) { if (interfaceType.IsGenericType) { Type genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(System.Collections.Generic.IDictionary<,>)) return interfaceType.GetGenericArguments()[0]; } } result = typeof(object); _keyTypeMap[type] = result; } return result; } private bool _isComposite; private bool _isCompositeCalculated; private IValueSerializerContext _context; private XamlDesignerSerializationManager _manager; } internal abstract class ElementObjectPropertyBase : ElementPropertyBase { protected ElementObjectPropertyBase(ElementMarkupObject obj): base(obj.Manager) { Debug.Assert(obj != null); _object = obj; } protected override IValueSerializerContext GetItemContext() { return _object.Context; } protected override Type GetObjectType() { return _object.ObjectType; } protected readonly ElementMarkupObject _object; } /// /// An implementation of MarkupProperty for DependencyObjects that works also for CLR only objects /// internal class ElementProperty : ElementObjectPropertyBase { internal ElementProperty(ElementMarkupObject obj, PropertyDescriptor descriptor) : base(obj) { Debug.Assert(descriptor != null); _descriptor = descriptor; } public override string Name { get { return _descriptor.Name; } } public override Type PropertyType { get { return _descriptor.PropertyType; } } public override PropertyDescriptor PropertyDescriptor { get { return _descriptor; } } public override bool IsAttached { get { UpdateDependencyProperty(); return _isAttached; } } public override DependencyProperty DependencyProperty { get { UpdateDependencyProperty(); return _dependencyProperty; } } public override object Value { get { object value; DependencyProperty DP = DependencyProperty; // For DPs, we use ReadLocalValue to find the property, and handle // unset values. if (DP != null) { DependencyObject DO = _object.Instance as DependencyObject; Debug.Assert(DO != null); // get the local value of the DP value = DO.ReadLocalValue(DP); // Expressions require special handling Expression expression = value as Expression; if (expression != null) { // Special-case: Expressions always get converted to an ME if // possible (and requested), and get de-referenced otherwise. TypeConverter converter = TypeDescriptor.GetConverter(value); if (Manager.XamlWriterMode == XamlWriterMode.Expression && converter.CanConvertTo(typeof(MarkupExtension))) { value = converter.ConvertTo(expression, typeof(MarkupExtension)); } else { value = expression.GetValue(DO, DP); } } // If the expression gave us UnsetValue, fall back to the default. if (value == DependencyProperty.UnsetValue) { value = DP.GetDefaultValue(DO.DependencyObjectType); } } // If this is the VisualTree property of a template, we have to do special processing. // Long-term plan is to replace this with an attribute on the type, that tells us how // to serialize its content. else if ((Name == "Template" || Name == "VisualTree") && Context.Instance is FrameworkTemplate && (Context.Instance as FrameworkTemplate).HasContent ) { // Instantiate the template, in un-optimized form. This makes the template content // load as if it were loaded from xaml outside a template. The only exception is that // TemplateBinding's will show up as a TemplateBindingExtension. value = (Context.Instance as FrameworkTemplate).LoadContent(); } // Otherwise, get the value from the property descriptor. else { value = _descriptor.GetValue(_object.Instance); } // Convert the resulting value from above into a MarkupExtension, if necessary/possible, // but only if there is no value serializer; if the type supports conversion to both // string and ME, we give preference to the string conversion. if( !(value is MarkupExtension) && !CanConvertToString(value) ) { value = CheckForMarkupExtension(PropertyType, value, Context, true); } return value; } } public override AttributeCollection Attributes { get { return _descriptor.Attributes; } } private void UpdateDependencyProperty() { if (!_isDependencyPropertyCached) { DependencyPropertyDescriptor dpDesc = DependencyPropertyDescriptor.FromProperty(_descriptor); if (dpDesc != null) { _dependencyProperty = dpDesc.DependencyProperty; _isAttached = dpDesc.IsAttached; } _isDependencyPropertyCached = true; } } // // Check for values that can be converted into markup extensions, either because // they are a well known type ((null, arrays, enums, and types), or because they // can be type converted into an ME. // internal static object CheckForMarkupExtension( Type propertyType, object value, IValueSerializerContext context, bool convertEnums) { // null => NullExtension if (value == null) { return new NullExtension(); } // See if the type has a type converter that can create a MarkupExtension // (Have to do this after the null check so that GetConverter doesn't get // an invalid argument.) TypeConverter converter = TypeDescriptor.GetConverter(value); if (converter.CanConvertTo(context, typeof(MarkupExtension))) { // The type provides a converter that creates a MarkupExtension. return converter.ConvertTo(context, TypeConverterHelper.InvariantEnglishUS, value, typeof(MarkupExtension)); } // System.Type => TypeExtension Type type = value as Type; if (type != null) { // If the property is declared to be a type already, we don't need to convert it // into {x:Type} syntax. if( propertyType == typeof(Type) ) { return value; } return new TypeExtension(type); } // Enums => StaticExtension if (convertEnums) { Enum enumValue = value as Enum; if (enumValue != null) { ValueSerializer typeSerializer = context.GetValueSerializerFor(typeof(Type)); Debug.Assert(typeSerializer != null, "typeSerializer for Enum was null"); string typeName = typeSerializer.ConvertToString(enumValue.GetType(), context); return new StaticExtension(typeName + "." + enumValue.ToString()); } } // Arrays => ArrayExtension Array array = value as Array; if (array != null) { return new ArrayExtension(array); } // Otherwise, value is unchanged. return value; } private PropertyDescriptor _descriptor; private bool _isDependencyPropertyCached; private DependencyProperty _dependencyProperty; private bool _isAttached; } ////// Pseudo-property for strings passed to a type converter /// internal class ElementStringValueProperty : MarkupProperty { internal ElementStringValueProperty(ElementMarkupObject obj) { _object = obj; } public override string Name { get { return "StringValue"; } } public override Type PropertyType { get { return typeof(string); } } public override bool IsValueAsString { get { return true; } } public override object Value { get { return StringValue; } } public override string StringValue { get { ValueSerializer serializer = ValueSerializer.GetSerializerFor(_object.ObjectType, _object.Context); Debug.Assert(serializer != null && serializer.CanConvertToString(_object.Instance, _object.Context), "StringValue property value created for a type that cannot be converted to string"); return serializer.ConvertToString(_object.Instance, _object.Context); } } public override IEnumerableItems { get { Debug.WriteLine("ElementMarkupObject.Items is not implemented"); return null; } } public override AttributeCollection Attributes { get { return AttributeCollection.Empty; } } public override IEnumerable TypeReferences { get { ValueSerializer serializer = ValueSerializer.GetSerializerFor(_object.ObjectType, _object.Context); Debug.Assert(serializer != null && serializer.CanConvertToString(_object.Instance, _object.Context), "StringValue property value created for a type that cannot be converted to string"); return serializer.TypeReferences(_object.Instance, _object.Context); } } private ElementMarkupObject _object; } /// /// Pseudo-property for the key of a dictionary element /// internal abstract class ElementPseudoPropertyBase : ElementObjectPropertyBase { internal ElementPseudoPropertyBase(object value, Type type, ElementMarkupObject obj) : base(obj) { _value = value; _type = type; } public override Type PropertyType { get { return _type; } } public override object Value { get { return ElementProperty.CheckForMarkupExtension(PropertyType, _value, Context, true /*convertEnums*/); } } public override AttributeCollection Attributes { get { return AttributeCollection.Empty; } } public override IEnumerableTypeReferences { get { return new Type[0]; } } private object _value; private Type _type; } /// /// Pseudo-property for the key of a dictionary element /// internal class ElementKey : ElementPseudoPropertyBase { internal ElementKey(object value, Type type, ElementMarkupObject obj) : base(value, type, obj) { } public override string Name { get { return "Key"; } } public override bool IsKey { get { return true; } } } ////// Pseudo-property for constructor arguments /// internal class ElementConstructorArgument : ElementPseudoPropertyBase { internal ElementConstructorArgument(object value, Type type, ElementMarkupObject obj) : base(value, type, obj) { } public override string Name { get { return "Argument"; } } public override bool IsConstructorArgument { get { return true; } } } ////// Pseudo-property for IEnumerable implementations /// internal class ElementItemsPseudoProperty : ElementPseudoPropertyBase { internal ElementItemsPseudoProperty(IEnumerable value, Type type, ElementMarkupObject obj) : base(value, type, obj) { _value = value; } public override string Name { get { return "Items"; } } public override bool IsContent { get { return true; } } public override bool IsComposite { get { return true; } } public override IEnumerableItems { get { foreach (object instance in _value) { yield return new ElementMarkupObject(instance, Manager); } } } IEnumerable _value; } /// /// Pseudo-property for IDictionary implementation /// internal class ElementDictionaryItemsPseudoProperty : ElementPseudoPropertyBase { internal ElementDictionaryItemsPseudoProperty(IDictionary value, Type type, ElementMarkupObject obj) : base(value, type, obj) { _value = value; } public override string Name { get { return "Entries"; } } public override bool IsContent { get { return true; } } public override bool IsComposite { get { return true; } } public override IEnumerableItems { get { foreach (DictionaryEntry entry in _value) { ElementMarkupObject item = new ElementMarkupObject(entry.Value, Manager); item.SetKey(new ElementKey(entry.Key, typeof(object), item)); yield return item; } } } IDictionary _value; } internal class ValueSerializerContextWrapper : IValueSerializerContext { IValueSerializerContext _baseContext; public ValueSerializerContextWrapper(IValueSerializerContext baseContext) { _baseContext = baseContext; } public ValueSerializer GetValueSerializerFor(PropertyDescriptor descriptor) { if (_baseContext != null) return _baseContext.GetValueSerializerFor(descriptor); else return null; } public ValueSerializer GetValueSerializerFor(Type type) { if (_baseContext != null) return _baseContext.GetValueSerializerFor(type); else return null; } public IContainer Container { get { if (_baseContext != null) return _baseContext.Container; else return null; } } public object Instance { get { if (_baseContext != null) return _baseContext.Instance; else return null; } } public void OnComponentChanged() { if (_baseContext != null) _baseContext.OnComponentChanged(); } public bool OnComponentChanging() { if (_baseContext != null) return _baseContext.OnComponentChanging(); else return true; } public PropertyDescriptor PropertyDescriptor { get { if (_baseContext != null) return _baseContext.PropertyDescriptor; else return null; } } public object GetService(Type serviceType) { if (_baseContext != null) return _baseContext.GetService(serviceType); else return null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WindowsToolbar.cs
- HScrollBar.cs
- RefreshEventArgs.cs
- WebBrowserDocumentCompletedEventHandler.cs
- CommentEmitter.cs
- OrderablePartitioner.cs
- BaseCAMarshaler.cs
- SqlDataSourceView.cs
- ImageListUtils.cs
- SqlRowUpdatingEvent.cs
- streamingZipPartStream.cs
- serverconfig.cs
- Model3DGroup.cs
- HttpRequestBase.cs
- PointIndependentAnimationStorage.cs
- ReachPrintTicketSerializer.cs
- OracleCommandSet.cs
- WSUtilitySpecificationVersion.cs
- ReplacementText.cs
- WebReferenceCollection.cs
- InputLanguage.cs
- DataGridRowClipboardEventArgs.cs
- NonceToken.cs
- ExecutionEngineException.cs
- DataListItem.cs
- NameHandler.cs
- ResourceManager.cs
- CTreeGenerator.cs
- RetrieveVirtualItemEventArgs.cs
- TableLayoutStyle.cs
- MatrixUtil.cs
- BigInt.cs
- AttachmentService.cs
- filewebresponse.cs
- DesignerTransactionCloseEvent.cs
- AuthenticateEventArgs.cs
- DetailsViewUpdateEventArgs.cs
- Quaternion.cs
- SerialReceived.cs
- controlskin.cs
- ErrorWrapper.cs
- DataGridViewRowStateChangedEventArgs.cs
- NumericExpr.cs
- CompositeCollectionView.cs
- SecurityStandardsManager.cs
- RegionIterator.cs
- ResourceAssociationType.cs
- XPathDocumentIterator.cs
- WebPartVerbsEventArgs.cs
- RadialGradientBrush.cs
- RectKeyFrameCollection.cs
- Attributes.cs
- IBuiltInEvidence.cs
- ExceptionUtil.cs
- _HTTPDateParse.cs
- MsmqNonTransactedPoisonHandler.cs
- BridgeDataReader.cs
- MultipleCopiesCollection.cs
- OuterGlowBitmapEffect.cs
- ProcessRequestArgs.cs
- FormatConvertedBitmap.cs
- GridViewItemAutomationPeer.cs
- CacheRequest.cs
- sitestring.cs
- EntityWrapper.cs
- WebPartConnectionsCloseVerb.cs
- AttributeAction.cs
- SystemColorTracker.cs
- HttpClientCertificate.cs
- XPathQilFactory.cs
- WebPartEventArgs.cs
- BaseTemplatedMobileComponentEditor.cs
- ToolstripProfessionalRenderer.cs
- InputProcessorProfilesLoader.cs
- TargetParameterCountException.cs
- NullNotAllowedCollection.cs
- EditorPartCollection.cs
- BinaryReader.cs
- DiffuseMaterial.cs
- DateTimeUtil.cs
- TypeExtension.cs
- HttpCookieCollection.cs
- _IPv4Address.cs
- PrivilegedConfigurationManager.cs
- ColumnResizeUndoUnit.cs
- WmlImageAdapter.cs
- QuerySetOp.cs
- ExpressionVisitorHelpers.cs
- ADMembershipUser.cs
- TextElementEnumerator.cs
- ExecutionEngineException.cs
- SelectionPattern.cs
- DataGridViewComboBoxEditingControl.cs
- SourceFileBuildProvider.cs
- TabRenderer.cs
- SystemIcons.cs
- ComponentGuaranteesAttribute.cs
- Literal.cs
- DBPropSet.cs
- LicenseException.cs