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)
}