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")); } Contract.EndContractBlock(); 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) { Contract.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 assRef = (LooselyLinkedResourceReference)value; value = assRef.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 <String, ResourceLocator>(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 { Contract.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) }
private object GetObject(string key, bool ignoreCase, bool isString) { if (key == null) { throw new ArgumentNullException(nameof(key)); } if (Reader == null || _resCache == null) { throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); } object value = null; ResourceLocator resLocation; lock (Reader) { if (Reader == null) { throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); } if (_defaultReader != null) { // 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) { Debug.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) { 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 <string, ResourceLocator>(StringComparer.OrdinalIgnoreCase); } 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 { Debug.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) }
public override Object GetObject(String key, bool ignoreCase) { if (key == null) { throw new ArgumentNullException("key"); } Hashtable copyOfTable = _table; if (Reader == null || copyOfTable == null) { throw new InvalidOperationException("ResourceSet is closed"); } Object value = copyOfTable[key]; if (value != null) { return(value); } lock (this) { if (Reader == null) { throw new InvalidOperationException("ResourceSet is closed"); } if (_defaultReader != null) { BCLDebug.Log("RESMGRFILEFORMAT", "Going down fast path in RuntimeResourceSet::GetObject"); int pos = _defaultReader.FindPosForResource(key); if (pos != -1) { value = _defaultReader.LoadObject(pos); // ResourceReader's Enumerator could also be filling in // values in _table, hence this lock. lock (_table) { Object v2 = _table[key]; if (v2 == null) { _table[key] = value; } else { value = v2; } } return(value); } else if (!ignoreCase) { return(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 Hashtable(new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture), new CaseInsensitiveComparer(CultureInfo.InvariantCulture)); } #if _DEBUG //Console.WriteLine("RuntimeResourceSet::GetObject loading up data. ignoreCase: "+ignoreCase); BCLDebug.Perf(!ignoreCase, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing " + key + " correctly in your source"); #endif IDictionaryEnumerator en = Reader.GetEnumerator(); while (en.MoveNext()) { if (_defaultReader == null) { _table.Add(en.Key, en.Value); } if (ignoreCase) { _caseInsensitiveTable.Add(en.Key, en.Value); } } // If we are doing a case-insensitive lookup, we don't want to // close our default reader since we may still use it for // case-sensitive lookups later. if (!ignoreCase) { Reader.Close(); } _haveReadFromReader = true; } Object obj = null; if (_defaultReader != null) { obj = _table[key]; } if (obj == null && ignoreCase) { obj = _caseInsensitiveTable[key]; } return(obj); } }