We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Resources \ ResourceSet

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  ResourceSet
  18. **
  19. **
  20. ** Purpose: Culture-specific collection of resources.
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Resources
  25. {
  26.     using System;
  27.     using System.Collections;
  28.     using System.IO;
  29.     using System.Runtime.Remoting.Activation;
  30.     using System.Globalization;
  31.     using System.Security.Permissions;
  32.     using System.Runtime.InteropServices;
  33.     using System.Reflection;
  34.     using System.Runtime.Serialization;
  35.     using System.Runtime.Versioning;
  36.    
  37.     // A ResourceSet stores all the resources defined in one particular CultureInfo.
  38.     //
  39.     // The method used to load resources is straightforward - this class
  40.     // enumerates over an IResourceReader, loading every name and value, and
  41.     // stores them in a hash table. Custom IResourceReaders can be used.
  42.     //
  43.     [Serializable()]
  44.     [System.Runtime.InteropServices.ComVisible(true)]
  45.     public class ResourceSet : IDisposable, IEnumerable
  46.     {
  47.         [NonSerialized()]
  48.         protected IResourceReader Reader;
  49.         protected Hashtable Table;
  50.        
  51.         private Hashtable _caseInsensitiveTable;
  52.         // For case-insensitive lookups.
  53.        
  54.         protected ResourceSet()
  55.         {
  56.             // To not inconvenience people subclassing us, we should allocate a new
  57.             // hashtable here just so that Table is set to something.
  58.             Table = new Hashtable(0);
  59.         }
  60.        
  61.         // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
  62.         // allocation.
  63.         internal ResourceSet(bool junk)
  64.         {
  65.         }
  66.        
  67.         // Creates a ResourceSet using the system default ResourceReader
  68.         // implementation. Use this constructor to open & read from a file
  69.         // on disk.
  70.         //
  71.         [ResourceExposure(ResourceScope.Machine)]
  72.         [ResourceConsumption(ResourceScope.Machine)]
  73.         public ResourceSet(string fileName)
  74.         {
  75.             Reader = new ResourceReader(fileName);
  76.             Table = new Hashtable();
  77.             ReadResources();
  78.         }
  79.        
  80.        
  81.         // Creates a ResourceSet using the system default ResourceReader
  82.         // implementation. Use this constructor to read from an open stream
  83.         // of data.
  84.         //
  85.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  86.         public ResourceSet(Stream stream)
  87.         {
  88.             Reader = new ResourceReader(stream);
  89.             Table = new Hashtable();
  90.             ReadResources();
  91.         }
  92.        
  93.        
  94.         public ResourceSet(IResourceReader reader)
  95.         {
  96.             if (reader == null)
  97.                 throw new ArgumentNullException("reader");
  98.             Reader = reader;
  99.             Table = new Hashtable();
  100.             ReadResources();
  101.         }
  102.        
  103.        
  104.         // Closes and releases any resources used by this ResourceSet, if any.
  105.         // All calls to methods on the ResourceSet after a call to close may
  106.         // fail. Close is guaranteed to be safely callable multiple times on a
  107.         // particular ResourceSet, and all subclasses must support these semantics.
  108.         public virtual void Close()
  109.         {
  110.             Dispose(true);
  111.         }
  112.        
  113.         protected virtual void Dispose(bool disposing)
  114.         {
  115.             if (disposing) {
  116.                 // Close the Reader in a thread-safe way.
  117.                 IResourceReader copyOfReader = Reader;
  118.                 Reader = null;
  119.                 if (copyOfReader != null)
  120.                     copyOfReader.Close();
  121.             }
  122.             Reader = null;
  123.             _caseInsensitiveTable = null;
  124.             Table = null;
  125.         }
  126.        
  127.         public void Dispose()
  128.         {
  129.             Dispose(true);
  130.         }
  131.        
  132.        
  133.         // Returns the preferred IResourceReader class for this kind of ResourceSet.
  134.         // Subclasses of ResourceSet using their own Readers &; should override
  135.         // GetDefaultReader and GetDefaultWriter.
  136.         public virtual Type GetDefaultReader()
  137.         {
  138.             return typeof(ResourceReader);
  139.         }
  140.        
  141.         // Returns the preferred IResourceWriter class for this kind of ResourceSet.
  142.         // Subclasses of ResourceSet using their own Readers &; should override
  143.         // GetDefaultReader and GetDefaultWriter.
  144.         public virtual Type GetDefaultWriter()
  145.         {
  146.             return typeof(ResourceWriter);
  147.         }
  148.        
  149.         [ComVisible(false)]
  150.         public virtual IDictionaryEnumerator GetEnumerator()
  151.         {
  152.             return GetEnumeratorHelper();
  153.         }
  154.        
  155.         /// <internalonly/>
  156.         IEnumerator IEnumerable.GetEnumerator()
  157.         {
  158.             return GetEnumeratorHelper();
  159.         }
  160.        
  161.         private IDictionaryEnumerator GetEnumeratorHelper()
  162.         {
  163.             Hashtable copyOfTable = Table;
  164.             // Avoid a race with Dispose
  165.             if (copyOfTable == null)
  166.                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
  167.             return copyOfTable.GetEnumerator();
  168.         }
  169.        
  170.         // Look up a string value for a resource given its name.
  171.         //
  172.         public virtual string GetString(string name)
  173.         {
  174.             Hashtable copyOfTable = Table;
  175.             // Avoid a race with Dispose
  176.             if (copyOfTable == null)
  177.                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
  178.             if (name == null)
  179.                 throw new ArgumentNullException("name");
  180.            
  181.             try {
  182.                 return (string)copyOfTable[name];
  183.             }
  184.             catch (InvalidCastException) {
  185.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
  186.             }
  187.         }
  188.        
  189.         public virtual string GetString(string name, bool ignoreCase)
  190.         {
  191.             Hashtable copyOfTable = Table;
  192.             // Avoid a race with Dispose
  193.             if (copyOfTable == null)
  194.                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
  195.             if (name == null)
  196.                 throw new ArgumentNullException("name");
  197.            
  198.             string s;
  199.             try {
  200.                 s = (string)copyOfTable[name];
  201.             }
  202.             catch (InvalidCastException) {
  203.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
  204.             }
  205.             if (s != null || !ignoreCase)
  206.                 return s;
  207.            
  208.             // Try doing a case-insensitive lookup.
  209.             Hashtable caseTable = _caseInsensitiveTable;
  210.             // Avoid race with Close
  211.             if (caseTable == null) {
  212.                 caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
  213.                 #if _DEBUG
  214.                 //Console.WriteLine("ResourceSet::GetString loading up data. ignoreCase: "+ignoreCase);
  215.                 BCLDebug.Perf(!ignoreCase, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing " + name + " correctly in your source");
  216.                 #endif
  217.                 IDictionaryEnumerator en = copyOfTable.GetEnumerator();
  218.                 while (en.MoveNext()) {
  219.                     caseTable.Add(en.Key, en.Value);
  220.                 }
  221.                 _caseInsensitiveTable = caseTable;
  222.             }
  223.             try {
  224.                 return (string)caseTable[name];
  225.             }
  226.             catch (InvalidCastException) {
  227.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
  228.             }
  229.         }
  230.        
  231.         // Look up an object value for a resource given its name.
  232.         //
  233.         public virtual object GetObject(string name)
  234.         {
  235.             Hashtable copyOfTable = Table;
  236.             // Avoid a race with Dispose
  237.             if (copyOfTable == null)
  238.                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
  239.             if (name == null)
  240.                 throw new ArgumentNullException("name");
  241.            
  242.             return copyOfTable[name];
  243.         }
  244.        
  245.         public virtual object GetObject(string name, bool ignoreCase)
  246.         {
  247.             Hashtable copyOfTable = Table;
  248.             // Avoid a race with Dispose
  249.             if (copyOfTable == null)
  250.                 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
  251.             if (name == null)
  252.                 throw new ArgumentNullException("name");
  253.            
  254.             object obj = copyOfTable[name];
  255.             if (obj != null || !ignoreCase)
  256.                 return obj;
  257.            
  258.             // Try doing a case-insensitive lookup.
  259.             Hashtable caseTable = _caseInsensitiveTable;
  260.             // Avoid race with Close
  261.             if (caseTable == null) {
  262.                 caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
  263.                 #if _DEBUG
  264.                 //Console.WriteLine("ResourceSet::GetObject loading up case-insensitive data");
  265.                 BCLDebug.Perf(!ignoreCase, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing " + name + " correctly in your source");
  266.                 #endif
  267.                 IDictionaryEnumerator en = copyOfTable.GetEnumerator();
  268.                 while (en.MoveNext()) {
  269.                     caseTable.Add(en.Key, en.Value);
  270.                 }
  271.                 _caseInsensitiveTable = caseTable;
  272.             }
  273.            
  274.             return caseTable[name];
  275.         }
  276.        
  277.         protected virtual void ReadResources()
  278.         {
  279.             IDictionaryEnumerator en = Reader.GetEnumerator();
  280.             while (en.MoveNext()) {
  281.                 object value = en.Value;
  282.                 Table.Add(en.Key, value);
  283.             }
  284.             // While technically possible to close the Reader here, don't close it
  285.             // to help with some WinRes lifetime issues.
  286.         }
  287.     }
  288. }

Developer Fusion