public virtual void ApplyResources(object value, string objectName, CultureInfo?culture) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (objectName == null) { throw new ArgumentNullException(nameof(objectName)); } if (culture == null) { culture = CultureInfo.CurrentUICulture; } // The general case here will be to always use the same culture, so optimize for // that. The resourceSets hashtable uses culture as a key. It's value is // a sorted dictionary that contains ALL the culture values (so it traverses up // the parent culture chain) for that culture. This means that if ApplyResources // is called with different cultures there could be some redundancy in the // table, but it allows the normal case of calling with a single culture to // be much faster. // // The reason we use a SortedDictionary here is to ensure the resources are applied // in an order consistent with codedom deserialization. SortedList <string, object?>?resources; if (_resourceSets == null) { _resourceSets = new Hashtable(); resources = FillResources(culture, out ResourceSet? dummy); _resourceSets[culture] = resources; } else { resources = (SortedList <string, object?>?)_resourceSets[culture]; if (resources == null || (resources.Comparer.Equals(StringComparer.OrdinalIgnoreCase) != IgnoreCase)) { resources = FillResources(culture, out ResourceSet? dummy); _resourceSets[culture] = resources; } } BindingFlags flags = BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance; if (IgnoreCase) { flags |= BindingFlags.IgnoreCase; } bool componentReflect = false; if (value is IComponent) { ISite?site = ((IComponent)value).Site; if (site != null && site.DesignMode) { componentReflect = true; } } foreach (KeyValuePair <string, object?> kvp in resources) { // See if this key matches our object. string key = kvp.Key; if (IgnoreCase) { if (string.Compare(key, 0, objectName, 0, objectName.Length, StringComparison.OrdinalIgnoreCase) != 0) { continue; } } else { if (string.CompareOrdinal(key, 0, objectName, 0, objectName.Length) != 0) { continue; } } // Character after objectName.Length should be a "." or a '-', or else we should continue. int idx = objectName.Length; if (key.Length <= idx || (key[idx] != '.' && key[idx] != '-')) { continue; } // Bypass type descriptor if we are not in design mode. TypeDescriptor does an attribute // scan which is quite expensive. string propName = key.Substring(idx + 1); if (componentReflect) { PropertyDescriptor?prop = TypeDescriptor.GetProperties(value).Find(propName, IgnoreCase); if (prop != null && !prop.IsReadOnly && (kvp.Value == null || prop.PropertyType.IsInstanceOfType(kvp.Value))) { prop.SetValue(value, kvp.Value); } } else { PropertyInfo?prop = null; try { prop = value.GetType().GetProperty(propName, flags); } catch (AmbiguousMatchException) { // Looks like we ran into a conflict between a declared property and an inherited one. // In such cases, we choose the most declared one. Type?t = value.GetType(); do { prop = t.GetProperty(propName, flags | BindingFlags.DeclaredOnly); t = t.BaseType; } while (prop == null && t != null && t != typeof(object)); } if (prop != null && prop.CanWrite && (kvp.Value == null || prop.PropertyType.IsInstanceOfType(kvp.Value))) { prop.SetValue(value, kvp.Value, null); } } } }
/// <include file='doc\ComponentResourceManager.uex' path='docs/doc[@for="ComponentResourceManager.ApplyResources1"]/*' /> /// <devdoc> /// This method examines all the resources for the provided culture. /// When it finds a resource with a key in the format of /// "[objectName].[property name]" it will apply that resource's value /// to the corresponding property on the object. If there is no matching /// property the resource will be ignored. /// </devdoc> public virtual void ApplyResources(object value, string objectName, CultureInfo culture) { if (value == null) { throw new ArgumentNullException("value"); } if (objectName == null) { throw new ArgumentNullException("objectName"); } if (culture == null) { culture = CultureInfo.CurrentUICulture; } // The general case here will be to always use the same culture, so optimize for // that. The resourceSets hashtable uses culture as a key. It's value is // another hashtable that contains ALL the culture values (so it traverses up // the parent culture chain) for that culture. This means that if ApplyResources // is called with different cultures there could be some redundancy in the // table, but it allows the normal case of calling with a single culture to // be much faster. // Hashtable resources; if (resourceSets == null) { ResourceSet dummy; resourceSets = new Hashtable(); resources = FillResources(culture, out dummy); resourceSets[culture] = resources; } else { resources = (Hashtable)resourceSets[culture]; if (resources == null || ((resources is CaseInsensitiveHashtable) != IgnoreCase)) { ResourceSet dummy; resources = FillResources(culture, out dummy); resourceSets[culture] = resources; } } BindingFlags flags = BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance; if (IgnoreCase) { flags |= BindingFlags.IgnoreCase; } bool componentReflect = false; if (value is IComponent) { ISite site = ((IComponent)value).Site; if (site != null && site.DesignMode) { componentReflect = true; } } foreach (DictionaryEntry de in resources) { // See if this key matches our object. // string key = de.Key as string; if (key == null) { continue; } if (IgnoreCase) { if (string.Compare(key, 0, objectName, 0, objectName.Length, true, CultureInfo.InvariantCulture) != 0) { continue; } } else { if (string.CompareOrdinal(key, 0, objectName, 0, objectName.Length) != 0) { continue; } } // Character after objectName.Length should be a ".", or else we should continue. // int idx = objectName.Length; if (key.Length <= idx || key[idx] != '.') { continue; } // Bypass type descriptor if we are not in design mode. TypeDescriptor does an attribute // scan which is quite expensive. // string propName = key.Substring(idx + 1); if (componentReflect) { PropertyDescriptor prop = TypeDescriptor.GetProperties(value).Find(propName, IgnoreCase); if (prop != null && !prop.IsReadOnly && (de.Value == null || prop.PropertyType.IsInstanceOfType(de.Value))) { prop.SetValue(value, de.Value); } } else { PropertyInfo prop = value.GetType().GetProperty(propName, flags); if (prop != null && prop.CanWrite && (de.Value == null || prop.PropertyType.IsInstanceOfType(de.Value))) { prop.SetValue(value, de.Value, null); } } } }
private void Child_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (RaiseListChangedEvents) { if (sender == null || e == null || string.IsNullOrEmpty(e.PropertyName)) { // Fire reset event (per INotifyPropertyChanged spec) ResetBindings(); } else { // The change event is broken should someone pass an item to us that is not // of type T. Still, if they do so, detect it and ignore. It is an incorrect // and rare enough occurrence that we do not want to slow the mainline path // with "is" checks. T item; try { item = (T)sender; } catch (InvalidCastException) { ResetBindings(); return; } // Find the position of the item. This should never be -1. If it is, // somehow the item has been removed from our list without our knowledge. int pos = _lastChangeIndex; if (pos < 0 || pos >= Count || !this[pos].Equals(item)) { pos = IndexOf(item); _lastChangeIndex = pos; } if (pos == -1) { Debug.Fail("Item is no longer in our list but we are still getting change notifications."); UnhookPropertyChanged(item); ResetBindings(); } else { // Get the property descriptor if (null == _itemTypeProperties) { // Get Shape _itemTypeProperties = TypeDescriptor.GetProperties(typeof(T)); Debug.Assert(_itemTypeProperties != null); } PropertyDescriptor pd = _itemTypeProperties.Find(e.PropertyName, true); // Create event args. If there was no matching property descriptor, // we raise the list changed anyway. ListChangedEventArgs args = new ListChangedEventArgs(ListChangedType.ItemChanged, pos, pd); // Fire the ItemChanged event OnListChanged(args); } } } }
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return(TypeDescriptor.GetProperties(value, attributes)); }