private Object GetObject(String key, bool ignoreCase, bool isString)
{
if (key==null)
throw new ArgumentNullException("key");
Dictionary<String, ResourceLocator> copyOfCache = _resCache;
if (Reader == null || copyOfCache == null)
throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
Object value = null;
ResourceLocator resLocation;
if (copyOfCache.TryGetValue(key, out resLocation)) {
value = ResolveResourceLocator(resLocation, key, copyOfCache, false);
return value;
}
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) {
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 {
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;
}
if (!found && ignoreCase) {
if (_caseInsensitiveTable.TryGetValue(key, out resLocation)) {
found = true;
keyInWrongCase = true;
}
}
if (found) {
obj = ResolveResourceLocator(resLocation, key, copyOfCache, keyInWrongCase);
}
return obj;
} // lock(Reader)
}