Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / ResourceDictionary.cs / 2 / ResourceDictionary.cs
/****************************************************************************\ * * File: ResourceDictionary.cs * * Dictionary that holds Resources for Framework components. * * Copyright (C) 2003 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.IO; using System.Net; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Diagnostics; using System.ComponentModel; using System.Windows.Threading; using System.Windows.Media; using System.Windows.Markup; using System.IO.Packaging; using MS.Internal.IO.Packaging; // for PackageCacheEntry using System.Globalization; using System.Windows.Navigation; using MS.Internal; using MS.Internal.Utility; using MS.Internal.AppModel; using MS.Utility; namespace System.Windows { ////// Dictionary that holds Resources for Framework components. /// [Localizability(LocalizationCategory.Ignore)] public class ResourceDictionary : IDictionary, INameScope, ISupportInitialize, IUriContext { #region Constructor ////// Constructor for ResourceDictionary /// public ResourceDictionary() { _baseDictionary = new Hashtable(); IsThemeDictionary = SystemResources.IsSystemResourcesParsing; } #endregion Constructor #region PublicAPIs ////// Copies the dictionary's elements to a one-dimensional /// Array instance at the specified index. /// /// /// The one-dimensional Array that is the destination of the /// DictionaryEntry objects copied from Hashtable. The Array /// must have zero-based indexing. /// /// /// The zero-based index in array at which copying begins. /// public void CopyTo(DictionaryEntry[] array, int arrayIndex) { if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { CopyToWithoutLock(array, arrayIndex); } } else { CopyToWithoutLock(array, arrayIndex); } } private void CopyToWithoutLock(DictionaryEntry[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } _baseDictionary.CopyTo(array, arrayIndex); int length = arrayIndex + Count; for (int i = arrayIndex; i < length; i++) { DictionaryEntry entry = array[i]; object value = entry.Value; bool canCache; if (RealizeDeferContent(entry.Key, ref value, out canCache)) { entry.Value = value; } } } ////// List of ResourceDictionaries merged into this Resource Dictionary /// public CollectionMergedDictionaries { get { if (_mergedDictionaries == null) { _mergedDictionaries = new ObservableCollection (); _mergedDictionaries.CollectionChanged += OnMergedDictionariesChanged; } return _mergedDictionaries; } } /// /// Uri to load this resource from, it will clear the current state of the ResourceDictionary /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Uri Source { get { return _source; } set { if (value == null || String.IsNullOrEmpty(value.OriginalString)) { throw new ArgumentException(SR.Get(SRID.ResourceDictionaryLoadFromFailure, value == null ? "''" : value.ToString())); } _source = value; Clear(); Uri uri = BindUriHelper.GetResolvedUri(_baseUri, _source); WebRequest request = WpfWebRequestHelper.CreateRequest(uri); WpfWebRequestHelper.ConfigCachePolicy(request, false); ContentType contentType; Stream s = WpfWebRequestHelper.GetResponseStream(request, out contentType); // MimeObjectFactory.GetObjectAndCloseStream will try to find the object converter basing on the mime type. // It can be a sync/async converter. It's the converter's responsiblity to close the stream. // If it fails to find a convert, this call will return null. XamlReader asyncObjectConverter; ResourceDictionary loadedRD = MimeObjectFactory.GetObjectAndCloseStream(s, contentType, uri, false, false, false /*allowAsync*/, false /*isJournalNavigation*/, out asyncObjectConverter) as ResourceDictionary; if (loadedRD == null) { throw new InvalidOperationException(SR.Get(SRID.ResourceDictionaryLoadFromFailure, _source.ToString())); } // ReferenceCopy all the key-value pairs in the _baseDictionary _baseDictionary = loadedRD._baseDictionary; // ReferenceCopy all the entries in the MergedDictionaries collection _mergedDictionaries = loadedRD._mergedDictionaries; // ReferenceCopy all of the deferred content state _buffer = loadedRD._buffer; _bamlStream = loadedRD._bamlStream; _startPosition = loadedRD._startPosition; _contentSize = loadedRD._contentSize; _context = loadedRD._context; _rootElement = loadedRD._rootElement; _reader = loadedRD._reader; _numDefer = loadedRD._numDefer; // Copy over the HasImplicitStyles flag HasImplicitStyles = loadedRD.HasImplicitStyles; } } #region INameScope ////// Registers the name - element combination /// /// name of the element /// Element where name is defined public void RegisterName(string name, object scopedElement) { throw new NotSupportedException(SR.Get(SRID.NamesNotSupportedInsideResourceDictionary)); } ////// Unregisters the name - element combination /// /// Name of the element public void UnregisterName(string name) { // Do Nothing as Names cannot be registered on ResourceDictionary } ////// Find the element given name /// /// Name of the element ///null always public object FindName(string name) { return null; } #endregion INameScope #region IUriContext ////// Accessor for the base uri of the ResourceDictionary /// Uri IUriContext.BaseUri { get { return _baseUri; } set { _baseUri = value; } } #endregion IUriContext #endregion PublicAPIs #region IDictionary ////// Gets a value indicating whether the IDictionary has a fixed size. /// public bool IsFixedSize { get { return _baseDictionary.IsFixedSize; } } ////// Gets a value indicating whether the ResourceDictionary is read-only. /// public bool IsReadOnly { get { return ReadPrivateFlag(PrivateFlags.IsReadOnly); } internal set { WritePrivateFlag(PrivateFlags.IsReadOnly, value); if (value == true) { // Seal all the styles and templates in this dictionary SealValues(); } // Set all the merged resource dictionaries as ReadOnly if (_mergedDictionaries != null) { for (int i = 0; i < _mergedDictionaries.Count; i++) { _mergedDictionaries[i].IsReadOnly = value; } } } } ////// Gets or sets the value associated with the specified key. /// ////// Fire Invalidations only for changes made after the Init Phase /// If the key is not found on this ResourceDictionary, it will look on any MergedDictionaries for it /// public object this[object key] { get { bool canCache; return GetValue(key, out canCache); } set { // Seal styles and templates within App and Theme dictionary SealValue(value); if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { SetValueWithoutLock(key, value); } } else { SetValueWithoutLock(key, value); } } } private void SetValueWithoutLock(object key, object value) { if (IsReadOnly) { throw new InvalidOperationException(SR.Get(SRID.ResourceDictionaryIsReadOnly)); } object oldValue = _baseDictionary[key]; if (oldValue != value) { // We need to validate all the deferred references that refer // to the old resource before we overwrite it. ValidateDeferredResourceReferences(key); if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Start, TraceResourceDictionary.AddResource, this, key, value ); } _baseDictionary[key] = value; // Update the HasImplicitStyles flag UpdateHasImplicitStyles(key); // Notify owners of the change and fire invalidate if already initialized NotifyOwners(new ResourcesChangeInfo(key)); if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Stop, TraceResourceDictionary.AddResource, this, key, value ); } } } internal object GetValue(object key, out bool canCache) { if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { return GetValueWithoutLock(key, out canCache); } } else { return GetValueWithoutLock(key, out canCache); } } private object GetValueWithoutLock(object key, out bool canCache) { object value = _baseDictionary[key]; if (value != null) { RealizeDeferContent(key, ref value, out canCache); } else { canCache = true; //Search for the value in the Merged Dictionaries if (_mergedDictionaries != null) { for (int i = MergedDictionaries.Count - 1; (i > -1); i--) { // Note that MergedDictionaries collection can also contain null values ResourceDictionary mergedDictionary = MergedDictionaries[i]; if (mergedDictionary != null) { value = mergedDictionary.GetValue(key, out canCache); if (value != null) { break; } } } } } return value; } // Gets the type of the value stored at the given key internal Type GetValueType(object key, out bool found) { found = false; Type valueType = null; object value = _baseDictionary[key]; if (value != null) { found = true; IBamlDictionaryKey keyRecord = value as IBamlDictionaryKey; if (keyRecord != null) { Debug.Assert(_numDefer > 0, "The stream was closed before all deferred content was loaded."); Int32 valuePosition = keyRecord.ValuePosition; BamlRecordReader previousRecordReader = _context.BamlReader; BamlRecordReader reader = Reader; _context.BamlReader = reader; try { // Remember the starting stream position, so that it can be repositioned // after the read to handle recursive operations on the same stream. Int64 startPosition = _bamlStream.Position; _bamlStream.Position = _startPosition + valuePosition; BamlElementStartRecord bamlElementStartRecord = (BamlElementStartRecord)reader.GetNextRecord(); valueType = reader.MapTable.GetTypeFromId(bamlElementStartRecord.TypeId); _bamlStream.Position = startPosition; } finally { // Restore the previousRecordReader into the context _context.BamlReader = previousRecordReader; } } else { valueType = value.GetType(); } } else { // Search for the value in the Merged Dictionaries if (_mergedDictionaries != null) { for (int i = MergedDictionaries.Count - 1; (i > -1); i--) { // Note that MergedDictionaries collection can also contain null values ResourceDictionary mergedDictionary = MergedDictionaries[i]; if (mergedDictionary != null) { valueType = mergedDictionary.GetValueType(key, out found); if (found) { break; } } } } } return valueType; } ////// Gets a copy of the ICollection containing the keys of the IDictionary. /// public ICollection Keys { get { object[] keysCollection = new object[Count]; _baseDictionary.Keys.CopyTo(keysCollection, 0); return keysCollection; } } ////// Gets an ICollection containing the values in the Hashtable /// ///An ICollection containing the values in the Hashtable public ICollection Values { get { return new ResourceValuesCollection(this); } } ////// Adds an entry /// ////// Fire Invalidations only for changes made after the Init Phase /// public void Add(object key, object value) { // Seal styles and templates within App and Theme dictionary SealValue(value); if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { AddWithoutLock(key, value); } } else { AddWithoutLock(key, value); } } private void AddWithoutLock(object key, object value) { if (IsReadOnly) { throw new InvalidOperationException(SR.Get(SRID.ResourceDictionaryIsReadOnly)); } if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Start, TraceResourceDictionary.AddResource, this, key, value ); } _baseDictionary.Add(key, value); // Update the HasImplicitKey flag UpdateHasImplicitStyles(key); // Notify owners of the change and fire invalidate if already initialized NotifyOwners(new ResourcesChangeInfo(key)); if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Stop, TraceResourceDictionary.AddResource, this, key, value ); } } ////// Removes all elements from the IDictionary. /// public void Clear() { if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { ClearWithoutLock(); } } else { ClearWithoutLock(); } } private void ClearWithoutLock() { if (IsReadOnly) { throw new InvalidOperationException(SR.Get(SRID.ResourceDictionaryIsReadOnly)); } if (Count > 0) { // We need to validate all the deferred references that refer // to the old resource before we clear it. ValidateDeferredResourceReferences(null); // remove inheritance context from all values that got it from // this dictionary RemoveInheritanceContextFromValues(); _baseDictionary.Clear(); // Notify owners of the change and fire invalidate if already initialized NotifyOwners(ResourcesChangeInfo.CatastrophicDictionaryChangeInfo); } } ////// Determines whether the IDictionary contains an element with the specified key. /// if the Key is not contained in this ResourceDictionary, it will check in the MergedDictionaries too /// public bool Contains(object key) { bool result = _baseDictionary.Contains(key); //Search for the value in the Merged Dictionaries if (_mergedDictionaries != null) { for (int i = MergedDictionaries.Count - 1; (i > -1) && !result; i--) { // Note that MergedDictionaries collection can also contain null values ResourceDictionary mergedDictionary = MergedDictionaries[i]; if (mergedDictionary != null) { result = mergedDictionary.Contains(key); } } } return result; } ////// Determines whether the IDictionary contains a BamlObjectFactory against the specified key. /// if the Key is not contained in this ResourceDictionary, it will check in the MergedDictionaries too /// internal bool ContainsBamlObjectFactory(object key) { return GetBamlObjectFactory(key) != null; } ////// Retrieves an IBamlDictionaryKey from the IDictionary using the specified key. /// If the Key is not contained in this ResourceDictionary, it will check in the MergedDictionaries too /// internal IBamlDictionaryKey GetBamlObjectFactory(object key) { if (_baseDictionary.Contains(key)) { return _baseDictionary[key] as IBamlDictionaryKey; } //Search for the value in the Merged Dictionaries if (_mergedDictionaries != null) { for (int i = MergedDictionaries.Count - 1; i > -1; i--) { // Note that MergedDictionaries collection can also contain null values ResourceDictionary mergedDictionary = MergedDictionaries[i]; if (mergedDictionary != null) { IBamlDictionaryKey keyRecord = mergedDictionary.GetBamlObjectFactory(key); if (keyRecord != null) { return keyRecord; } } } } return null; } ////// Returns an IDictionaryEnumerator that can iterate through the Hashtable /// ///An IDictionaryEnumerator for the Hashtable public IDictionaryEnumerator GetEnumerator() { return new ResourceDictionaryEnumerator(this); } ////// Removes an entry /// ////// Fire Invalidations only for changes made after the Init Phase /// public void Remove(object key) { if (CanBeAccessedAcrossThreads) { lock(((ICollection)this).SyncRoot) { RemoveWithoutLock(key); } } else { RemoveWithoutLock(key); } } private void RemoveWithoutLock(object key) { if (IsReadOnly) { throw new InvalidOperationException(SR.Get(SRID.ResourceDictionaryIsReadOnly)); } // We need to validate all the deferred references that refer // to the old resource before we remove it. ValidateDeferredResourceReferences(key); // remove the inheritance context from the value, if it came from // this dictionary RemoveInheritanceContext(_baseDictionary[key]); _baseDictionary.Remove(key); // Notify owners of the change and fire invalidate if already initialized NotifyOwners(new ResourcesChangeInfo(key)); } #endregion IDictionary #region ICollection ////// Gets the number of elements contained in the ICollection. /// public int Count { get { return _baseDictionary.Count; } } ////// Gets a value indicating whether access to the ICollection is synchronized (thread-safe). /// bool ICollection.IsSynchronized { get { return _baseDictionary.IsSynchronized; } } ////// Gets an object that can be used to synchronize access to the ICollection. /// object ICollection.SyncRoot { get { if (CanBeAccessedAcrossThreads) { // Notice that we are acquiring the ThemeDictionaryLock. This // is because the _parserContext used for template expansion // shares data-structures such as the BamlMapTable and // XamlTypeMapper with the parent ParserContext that was used // to build the template in the first place. So if this template // is from the App.Resources then the ParserContext that is used for // loading deferred content in the app dictionary and the // _parserContext used to load template content share the same // instances of BamlMapTable and XamlTypeMapper. Hence we need to // make sure that we lock on the same object inorder to serialize // access to these data-structures in multi-threaded scenarios. // Look at comment in Frameworktemplate.LoadContent to understand // why we use the ThemeDictionaryLock for template expansion. return SystemResources.ThemeDictionaryLock; } else { return _baseDictionary.SyncRoot; } } } ////// Copies the dictionary's elements to a one-dimensional /// Array instance at the specified index. /// /// /// The one-dimensional Array that is the destination of the /// DictionaryEntry objects copied from Hashtable. The Array /// must have zero-based indexing. /// /// /// The zero-based index in array at which copying begins. /// void ICollection.CopyTo(Array array, int arrayIndex) { CopyTo(array as DictionaryEntry[], arrayIndex); } #endregion ICollection #region IEnumerable IEnumerator IEnumerable.GetEnumerator() { return ((IDictionary)this).GetEnumerator(); } #endregion IEnumerable #region ISupportInitialize ////// Mark the begining of the Init phase /// ////// BeginInit and EndInit follow a transaction model. BeginInit marks the /// dictionary uninitialized and EndInit marks it initialized. /// public void BeginInit() { // Nested BeginInits on the same instance aren't permitted if (IsInitializePending) { throw new InvalidOperationException(SR.Get(SRID.NestedBeginInitNotSupported)); } IsInitializePending = true; IsInitialized = false; } ////// Fire Invalidation at the end of Init phase /// ////// BeginInit and EndInit follow a transaction model. BeginInit marks the /// dictionary uninitialized and EndInit marks it initialized. /// public void EndInit() { // EndInit without a BeginInit isn't permitted if (!IsInitializePending) { throw new InvalidOperationException(SR.Get(SRID.EndInitWithoutBeginInitNotSupported)); } Debug.Assert(IsInitialized == false, "Dictionary should not be initialized when EndInit is called"); IsInitializePending = false; IsInitialized = true; // Fire Invalidations collectively for all changes made during the Init Phase NotifyOwners(new ResourcesChangeInfo(null, this)); } #endregion ISupportInitialize #region DeferContent private bool CanCache(IBamlDictionaryKey keyRecord, object value) { if (keyRecord.SharedSet) { return keyRecord.Shared; } else { return true; } } private bool RealizeDeferContent(ref object value) { bool canCache; return RealizeDeferContent(null, ref value, out canCache); } private bool RealizeDeferContent(object key, ref object value, out bool canCache) { IBamlDictionaryKey keyRecord = value as IBamlDictionaryKey; if (keyRecord != null) { Debug.Assert(_numDefer > 0, "The stream was closed before all deferred content was loaded."); Int32 valuePosition = keyRecord.ValuePosition; // Store the StaticResources list for the current key record into the parserContext so that // StaticResourceId records within the current value can use it for lookup. _context.StaticResourcesStack.Add(keyRecord.StaticResourceValues); try { if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Start, TraceResourceDictionary.RealizeDeferContent, this, key, value ); } value = CreateObject(valuePosition, key); } finally { if( TraceResourceDictionary.IsEnabled ) { TraceResourceDictionary.Trace( TraceEventType.Stop, TraceResourceDictionary.RealizeDeferContent, this, key, value ); } _context.StaticResourcesStack.RemoveAt(_context.StaticResourcesStack.Count-1); } if (key != null) { canCache = CanCache(keyRecord, value); if (canCache) { // Seal styles and templates within App and Theme dictionary SealValue(value); _numDefer--; _baseDictionary[key] = value; if (_numDefer == 0) { _reader = null; _context = null; // Only close the stream if it was a Memory Stream // built over our buffer. if(null != _buffer) { _bamlStream.Close(); _bamlStream = null; _buffer = null; } } } } else { canCache = true; } return true; /* Defer content */ } canCache = true; return false; /* Not defer content */ } ////// Add a byte array that contains deferable content /// internal void SetDeferableContent( byte[] buffer, ParserContext context, object rootElement, ArrayList keyCollection, List
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ToggleProviderWrapper.cs
- MeasureData.cs
- ReversePositionQuery.cs
- DataContractSerializerOperationGenerator.cs
- MenuItemCollectionEditor.cs
- New.cs
- GraphicsContainer.cs
- DataMemberAttribute.cs
- NativeBuffer.cs
- SqlCaseSimplifier.cs
- FormatConvertedBitmap.cs
- TargetConverter.cs
- ConfigurationManagerHelperFactory.cs
- ListBoxItemAutomationPeer.cs
- FeatureSupport.cs
- CacheModeConverter.cs
- Cursors.cs
- Evidence.cs
- InstancePersistenceContext.cs
- StringResourceManager.cs
- DynamicUpdateCommand.cs
- LinqDataSourceValidationException.cs
- FailedToStartupUIException.cs
- ResourceDescriptionAttribute.cs
- ObjectMemberMapping.cs
- DataPagerField.cs
- XmlArrayItemAttributes.cs
- CodeAttributeArgument.cs
- OrderPreservingPipeliningSpoolingTask.cs
- DataGridPagerStyle.cs
- SQLInt32.cs
- SecureStringHasher.cs
- StdValidatorsAndConverters.cs
- PolyBezierSegment.cs
- BitmapPalette.cs
- Matrix.cs
- ManifestSignatureInformation.cs
- EntityDataSourceWizardForm.cs
- HttpClientCertificate.cs
- ConstraintStruct.cs
- CommonRemoteMemoryBlock.cs
- AuthenticationException.cs
- AsyncOperation.cs
- EntityReference.cs
- TripleDES.cs
- RegexReplacement.cs
- ThreadStartException.cs
- RequestQueryParser.cs
- ContentPosition.cs
- TypographyProperties.cs
- CompensationHandlingFilter.cs
- IncrementalReadDecoders.cs
- ToolBarButton.cs
- WsdlEndpointConversionContext.cs
- DataSourceXmlElementAttribute.cs
- SrgsGrammar.cs
- FontFaceLayoutInfo.cs
- WsatAdminException.cs
- RegisteredArrayDeclaration.cs
- FragmentQueryProcessor.cs
- PathFigureCollectionConverter.cs
- HMAC.cs
- CustomValidator.cs
- XmlTextEncoder.cs
- PeerNameRegistration.cs
- Unit.cs
- StoreItemCollection.cs
- ModelTreeEnumerator.cs
- FilterElement.cs
- TextDecorationLocationValidation.cs
- RelationshipConstraintValidator.cs
- PeerTransportSecurityElement.cs
- GCHandleCookieTable.cs
- PropertyTabChangedEvent.cs
- WhitespaceRule.cs
- OdbcFactory.cs
- Group.cs
- MultipleCopiesCollection.cs
- _AutoWebProxyScriptHelper.cs
- DataKey.cs
- WpfXamlMember.cs
- NamespaceDisplay.xaml.cs
- WorkflowMarkupSerializationProvider.cs
- SqlConnectionStringBuilder.cs
- FixedSOMTextRun.cs
- RecordBuilder.cs
- PrintControllerWithStatusDialog.cs
- XmlSchemaObjectTable.cs
- RadioButtonBaseAdapter.cs
- DataBoundControl.cs
- Menu.cs
- Helpers.cs
- QueryContext.cs
- KnownIds.cs
- EventDescriptor.cs
- BitmapEffectGroup.cs
- TabItem.cs
- PropertyMetadata.cs
- HtmlMeta.cs
- CodeNamespaceImport.cs