| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- /*============================================================
- **
- **
- **
- **
- **
- ** Purpose: Culture-specific collection of resources.
- **
- **
- ===========================================================*/
- using System.Collections;
- using System.IO;
- using System.Reflection;
- namespace System.Resources
- {
- // A ResourceSet stores all the resources defined in one particular CultureInfo.
- //
- // The method used to load resources is straightforward - this class
- // enumerates over an IResourceReader, loading every name and value, and
- // stores them in a hash table. Custom IResourceReaders can be used.
- //
- public class ResourceSet : IDisposable, IEnumerable
- {
- protected IResourceReader Reader;
- internal Hashtable Table;
- private Hashtable _caseInsensitiveTable; // For case-insensitive lookups.
- protected ResourceSet()
- {
- // To not inconvenience people subclassing us, we should allocate a new
- // hashtable here just so that Table is set to something.
- CommonInit();
- }
- // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
- // allocation.
- internal ResourceSet(bool junk)
- {
- }
- // Creates a ResourceSet using the system default ResourceReader
- // implementation. Use this constructor to open & read from a file
- // on disk.
- //
- public ResourceSet(string fileName)
- {
- Reader = new ResourceReader(fileName);
- CommonInit();
- ReadResources();
- }
- // Creates a ResourceSet using the system default ResourceReader
- // implementation. Use this constructor to read from an open stream
- // of data.
- //
- public ResourceSet(Stream stream)
- {
- Reader = new ResourceReader(stream);
- CommonInit();
- ReadResources();
- }
- public ResourceSet(IResourceReader reader)
- {
- if (reader == null)
- throw new ArgumentNullException(nameof(reader));
- Reader = reader;
- CommonInit();
- ReadResources();
- }
- private void CommonInit()
- {
- Table = new Hashtable();
- }
- // Closes and releases any resources used by this ResourceSet, if any.
- // All calls to methods on the ResourceSet after a call to close may
- // fail. Close is guaranteed to be safely callable multiple times on a
- // particular ResourceSet, and all subclasses must support these semantics.
- public virtual void Close()
- {
- Dispose(true);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- // Close the Reader in a thread-safe way.
- IResourceReader copyOfReader = Reader;
- Reader = null;
- if (copyOfReader != null)
- copyOfReader.Close();
- }
- Reader = null;
- _caseInsensitiveTable = null;
- Table = null;
- }
- public void Dispose()
- {
- Dispose(true);
- }
- // Returns the preferred IResourceReader class for this kind of ResourceSet.
- // Subclasses of ResourceSet using their own Readers &; should override
- // GetDefaultReader and GetDefaultWriter.
- public virtual Type GetDefaultReader()
- {
- return typeof(ResourceReader);
- }
- // Returns the preferred IResourceWriter class for this kind of ResourceSet.
- // Subclasses of ResourceSet using their own Readers &; should override
- // GetDefaultReader and GetDefaultWriter.
- public virtual Type GetDefaultWriter()
- {
- Assembly resourceWriterAssembly = Assembly.Load("System.Resources.Writer, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
- return resourceWriterAssembly.GetType("System.Resources.ResourceWriter", true);
- }
- public virtual IDictionaryEnumerator GetEnumerator()
- {
- return GetEnumeratorHelper();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumeratorHelper();
- }
- private IDictionaryEnumerator GetEnumeratorHelper()
- {
- Hashtable copyOfTable = Table; // Avoid a race with Dispose
- if (copyOfTable == null)
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- return copyOfTable.GetEnumerator();
- }
- // Look up a string value for a resource given its name.
- //
- public virtual string GetString(string name)
- {
- object obj = GetObjectInternal(name);
- try
- {
- return (string)obj;
- }
- catch (InvalidCastException)
- {
- throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
- }
- }
- public virtual string GetString(string name, bool ignoreCase)
- {
- object obj;
- string s;
- // Case-sensitive lookup
- obj = GetObjectInternal(name);
- try
- {
- s = (string)obj;
- }
- catch (InvalidCastException)
- {
- throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
- }
- // case-sensitive lookup succeeded
- if (s != null || !ignoreCase)
- {
- return s;
- }
- // Try doing a case-insensitive lookup
- obj = GetCaseInsensitiveObjectInternal(name);
- try
- {
- return (string)obj;
- }
- catch (InvalidCastException)
- {
- throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
- }
- }
- // Look up an object value for a resource given its name.
- //
- public virtual object GetObject(string name)
- {
- return GetObjectInternal(name);
- }
- public virtual object GetObject(string name, bool ignoreCase)
- {
- object obj = GetObjectInternal(name);
- if (obj != null || !ignoreCase)
- return obj;
- return GetCaseInsensitiveObjectInternal(name);
- }
- protected virtual void ReadResources()
- {
- IDictionaryEnumerator en = Reader.GetEnumerator();
- while (en.MoveNext())
- {
- object value = en.Value;
- Table.Add(en.Key, value);
- }
- // While technically possible to close the Reader here, don't close it
- // to help with some WinRes lifetime issues.
- }
- private object GetObjectInternal(string name)
- {
- if (name == null)
- throw new ArgumentNullException(nameof(name));
- Hashtable copyOfTable = Table; // Avoid a race with Dispose
- if (copyOfTable == null)
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- return copyOfTable[name];
- }
- private object GetCaseInsensitiveObjectInternal(string name)
- {
- Hashtable copyOfTable = Table; // Avoid a race with Dispose
- if (copyOfTable == null)
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- Hashtable caseTable = _caseInsensitiveTable; // Avoid a race condition with Close
- if (caseTable == null)
- {
- caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
- IDictionaryEnumerator en = copyOfTable.GetEnumerator();
- while (en.MoveNext())
- {
- caseTable.Add(en.Key, en.Value);
- }
- _caseInsensitiveTable = caseTable;
- }
- return caseTable[name];
- }
- }
- }
|