Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Resources / RuntimeResourceSet.cs / 3 / RuntimeResourceSet.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: RuntimeResourceSet ** ** ** Purpose: CultureInfo-specific collection of resources. ** ** ===========================================================*/ namespace System.Resources { using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.Versioning; // A RuntimeResourceSet stores all the resources defined in one // particular CultureInfo, with some loading optimizations. // // It is expected that nearly all the runtime's users will be satisfied with the // default resource file format, and it will be more efficient than most simple // implementations. Users who would internal sealed class RuntimeResourceSet : ResourceSet, IEnumerable { internal const int Version = 2; // File format version number // Cache for resources. Key is the resource name, which can be cached // for arbitrarily long times, since the object is usually a string // literal that will live for the lifetime of the appdomain. The // value is a ResourceLocator instance, which might cache the object. private Dictionary_resCache; // For our special load-on-demand reader, cache the cast. The // RuntimeResourceSet's implementation knows how to treat this reader specially. private ResourceReader _defaultReader; // This is a lookup table for case-insensitive lookups, and may be null. // Consider always using a case-insensitive resource cache, as we don't // want to fill this out if we can avoid it. The problem is resource // fallback will somewhat regularly cause us to look up resources that // don't exist. private Dictionary _caseInsensitiveTable; // If we're not using our custom reader, then enumerate through all // the resources once, adding them into the table. private bool _haveReadFromReader; [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal RuntimeResourceSet(String fileName) : base(false) { BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(String)"); _resCache = new Dictionary (FastResourceComparer.Default); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); _defaultReader = new ResourceReader(stream, _resCache); Reader = _defaultReader; } #if LOOSELY_LINKED_RESOURCE_REFERENCE internal RuntimeResourceSet(Stream stream, Assembly assembly) : base(false) #else internal RuntimeResourceSet(Stream stream) : base(false) #endif // LOOSELY_LINKED_RESOURCE_REFERENCE { BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(Stream)"); _resCache = new Dictionary (FastResourceComparer.Default); _defaultReader = new ResourceReader(stream, _resCache); Reader = _defaultReader; #if LOOSELY_LINKED_RESOURCE_REFERENCE Assembly = assembly; #endif // LOOSELY_LINKED_RESOURCE_REFERENCE } protected override void Dispose(bool disposing) { if (Reader == null) return; if (disposing) { lock(Reader) { _resCache = null; if (_defaultReader != null) { _defaultReader.Close(); _defaultReader = null; } _caseInsensitiveTable = null; // Set Reader to null to avoid a race in GetObject. base.Dispose(disposing); } } else { // Just to make sure we always clear these fields in the _resCache = null; _caseInsensitiveTable = null; _defaultReader = null; base.Dispose(disposing); } } public override IDictionaryEnumerator GetEnumerator() { return GetEnumeratorHelper(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumeratorHelper(); } private IDictionaryEnumerator GetEnumeratorHelper() { IResourceReader copyOfReader = Reader; if (copyOfReader == null || _resCache == null) throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet")); return copyOfReader.GetEnumerator(); } public override String GetString(String key) { Object o = GetObject(key, false, true); return (String) o; } public override String GetString(String key, bool ignoreCase) { Object o = GetObject(key, ignoreCase, true); return (String) o; } public override Object GetObject(String key) { return GetObject(key, false, false); } public override Object GetObject(String key, bool ignoreCase) { return GetObject(key, ignoreCase, false); } private Object GetObject(String key, bool ignoreCase, bool isString) { if (key==null) throw new ArgumentNullException("key"); if (Reader == null || _resCache == null) throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet")); Object value = null; ResourceLocator resLocation; lock(Reader) { if (Reader == null) throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet")); if (_defaultReader != null) { BCLDebug.Log("RESMGRFILEFORMAT", "Going down fast path in RuntimeResourceSet::GetObject"); // Find the offset within the data section int dataPos = -1; if (_resCache.TryGetValue(key, out resLocation)) { value = resLocation.Value; dataPos = resLocation.DataPosition; } if (dataPos == -1 && value == null) { dataPos = _defaultReader.FindPosForResource(key); } if (dataPos != -1 && value == null) { BCLDebug.Assert(dataPos >= 0, "data section offset cannot be negative!"); // Normally calling LoadString or LoadObject requires // taking a lock. Note that in this case, we took a // lock on the entire RuntimeResourceSet, which is // sufficient since we never pass this ResourceReader // to anyone else. ResourceTypeCode typeCode; if (isString) { value = _defaultReader.LoadString(dataPos); typeCode = ResourceTypeCode.String; } else { value = _defaultReader.LoadObject(dataPos, out typeCode); } resLocation = new ResourceLocator(dataPos, (ResourceLocator.CanCache(typeCode)) ? value : null); lock(_resCache) { _resCache[key] = resLocation; } } if (value != null || !ignoreCase) { #if LOOSELY_LINKED_RESOURCE_REFERENCE if (Assembly != null && (value is LooselyLinkedResourceReference)) { LooselyLinkedResourceReference ----Ref = (LooselyLinkedResourceReference) value; value = ----Ref.Resolve(Assembly); } #endif // LOOSELY_LINKED_RESOURCE_REFERENCE return value; // may be null } } // if (_defaultReader != null) // At this point, we either don't have our default resource reader // or we haven't found the particular resource we're looking for // and may have to search for it in a case-insensitive way. if (!_haveReadFromReader) { // If necessary, init our case insensitive hash table. if (ignoreCase && _caseInsensitiveTable == null) { _caseInsensitiveTable = new Dictionary (StringComparer.OrdinalIgnoreCase); } #if _DEBUG BCLDebug.Perf(!ignoreCase, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing "+key+" correctly in your source"); #endif if (_defaultReader == null) { IDictionaryEnumerator en = Reader.GetEnumerator(); while (en.MoveNext()) { DictionaryEntry entry = en.Entry; String readKey = (String) entry.Key; ResourceLocator resLoc = new ResourceLocator(-1, entry.Value); _resCache.Add(readKey, resLoc); if (ignoreCase) _caseInsensitiveTable.Add(readKey, resLoc); } // Only close the reader if it is NOT our default one, // since we need it around to resolve ResourceLocators. if (!ignoreCase) Reader.Close(); } else { BCLDebug.Assert(ignoreCase, "This should only happen for case-insensitive lookups"); ResourceReader.ResourceEnumerator en = _defaultReader.GetEnumeratorInternal(); while (en.MoveNext()) { // Note: Always ask for the resource key before the data position. String currentKey = (String) en.Key; int dataPos = en.DataPosition; ResourceLocator resLoc = new ResourceLocator(dataPos, null); _caseInsensitiveTable.Add(currentKey, resLoc); } } _haveReadFromReader = true; } Object obj = null; bool found = false; bool keyInWrongCase = false; if (_defaultReader != null) { if (_resCache.TryGetValue(key, out resLocation)) { found = true; obj = ResolveResourceLocator(resLocation, key, _resCache, keyInWrongCase); } } if (!found && ignoreCase) { if (_caseInsensitiveTable.TryGetValue(key, out resLocation)) { found = true; keyInWrongCase = true; obj = ResolveResourceLocator(resLocation, key, _resCache, keyInWrongCase); } } return obj; } // lock(Reader) } // The last parameter indicates whether the lookup required a // case-insensitive lookup to succeed, indicating we shouldn't add // the ResourceLocation to our case-sensitive cache. private Object ResolveResourceLocator(ResourceLocator resLocation, String key, Dictionary copyOfCache, bool keyInWrongCase) { // We need to explicitly resolve loosely linked manifest // resources, and we need to resolve ResourceLocators with null objects. Object value = resLocation.Value; if (value == null) { ResourceTypeCode typeCode; lock(Reader) { value = _defaultReader.LoadObject(resLocation.DataPosition, out typeCode); } if (!keyInWrongCase && ResourceLocator.CanCache(typeCode)) { resLocation.Value = value; copyOfCache[key] = resLocation; } } #if LOOSELY_LINKED_RESOURCE_REFERENCE if (Assembly != null && value is LooselyLinkedResourceReference) { LooselyLinkedResourceReference ----Ref = (LooselyLinkedResourceReference) value; value = ----Ref.Resolve(Assembly); } #endif // LOOSELY_LINKED_RESOURCE_REFERENCE return value; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TimeoutException.cs
- DefaultObjectMappingItemCollection.cs
- HttpApplicationFactory.cs
- DataKey.cs
- TextServicesCompartmentEventSink.cs
- DataSourceExpressionCollection.cs
- SmtpAuthenticationManager.cs
- WaitHandle.cs
- MouseBinding.cs
- XmlBindingWorker.cs
- DbParameterCollectionHelper.cs
- UnmanagedMarshal.cs
- Image.cs
- CTreeGenerator.cs
- DbCommandTree.cs
- InputScopeNameConverter.cs
- PropertyValueUIItem.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- LocalServiceSecuritySettings.cs
- SetIndexBinder.cs
- UrlPropertyAttribute.cs
- HostedHttpContext.cs
- NumberFormatter.cs
- DataService.cs
- HMACSHA256.cs
- BrushMappingModeValidation.cs
- PictureBox.cs
- ConditionalDesigner.cs
- ChildDocumentBlock.cs
- GACIdentityPermission.cs
- PublishLicense.cs
- AsymmetricSignatureDeformatter.cs
- BaseCAMarshaler.cs
- OperatingSystem.cs
- DBCommand.cs
- ToggleProviderWrapper.cs
- SoapServerProtocol.cs
- FixedTextSelectionProcessor.cs
- hresults.cs
- TreeBuilder.cs
- TearOffProxy.cs
- AdCreatedEventArgs.cs
- ConcurrentQueue.cs
- ProgressBarBrushConverter.cs
- WebPartCatalogAddVerb.cs
- AncestorChangedEventArgs.cs
- CheckBoxDesigner.cs
- MethodExecutor.cs
- ListDictionaryInternal.cs
- VirtualDirectoryMappingCollection.cs
- MouseDevice.cs
- AnnotationAuthorChangedEventArgs.cs
- AppLevelCompilationSectionCache.cs
- ObjectHelper.cs
- MachineKeySection.cs
- DecimalAnimation.cs
- SoapAttributeAttribute.cs
- XmlSchemaElement.cs
- CaseCqlBlock.cs
- DependencySource.cs
- WebPartRestoreVerb.cs
- Pts.cs
- SQLBytesStorage.cs
- OracleCommandSet.cs
- BrowserDefinition.cs
- ZipIOLocalFileBlock.cs
- APCustomTypeDescriptor.cs
- PeerNameRecordCollection.cs
- ProgressBarHighlightConverter.cs
- SatelliteContractVersionAttribute.cs
- SQLBytes.cs
- SqlMethodTransformer.cs
- codemethodreferenceexpression.cs
- Span.cs
- SerializationException.cs
- EncryptedKey.cs
- Point3DKeyFrameCollection.cs
- PropertyBuilder.cs
- ComplusEndpointConfigContainer.cs
- WebPartMenu.cs
- DataGridViewColumn.cs
- ConfigurationException.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- log.cs
- MultipleViewProviderWrapper.cs
- Preprocessor.cs
- GridViewRowCollection.cs
- OleDbErrorCollection.cs
- ListenerServiceInstallComponent.cs
- sqlinternaltransaction.cs
- ValidationError.cs
- ExceptionAggregator.cs
- ValueTypeFieldReference.cs
- Serializer.cs
- VBIdentifierDesigner.xaml.cs
- Error.cs
- Internal.cs
- FunctionImportMapping.ReturnTypeRenameMapping.cs
- Assert.cs
- TextEditorCopyPaste.cs