2 // System.Resources.ResourceManager.cs
5 // Duncan Mak (duncan@ximian.com)
6 // Dick Porter (dick@ximian.com)
8 // (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 using System.Collections;
12 using System.Reflection;
13 using System.Globalization;
16 namespace System.Resources
19 public class ResourceManager
21 public static readonly int HeaderVersionNumber = 1;
22 public static readonly int MagicNumber = unchecked((int)0xBEEFCACE);
24 protected string BaseNameField;
25 protected Assembly MainAssembly;
26 // Maps cultures to ResourceSet objects
27 protected Hashtable ResourceSets;
29 private bool ignoreCase;
30 private Type resourceSetType;
31 private String resourceDir;
33 /* Recursing through culture parents stops here */
34 private CultureInfo neutral_culture;
37 protected ResourceManager () {
38 ResourceSets=new Hashtable();
40 resourceSetType=typeof(ResourceSet);
45 public ResourceManager (Type resourceSource) : this()
47 if (resourceSource == null)
48 throw new ArgumentNullException ("resourceSource is null.");
50 BaseNameField = resourceSource.FullName;
51 MainAssembly = resourceSource.Assembly;
53 /* Temporary workaround for bug 43567 */
54 resourceSetType = typeof(ResourceSet);
55 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
58 public ResourceManager (string baseName, Assembly assembly) : this()
61 throw new ArgumentNullException ("baseName is null.");
63 throw new ArgumentNullException ("assembly is null.");
65 BaseNameField = baseName;
66 MainAssembly = assembly;
67 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
70 private Type CheckResourceSetType(Type usingResourceSet)
72 if(usingResourceSet==null) {
73 return(typeof(ResourceSet));
75 if (!usingResourceSet.IsSubclassOf (typeof (ResourceSet)))
76 throw new ArgumentException ("Type must be from ResourceSet.");
78 return(usingResourceSet);
82 public ResourceManager (string baseName, Assembly assembly, Type usingResourceSet) : this()
85 throw new ArgumentNullException ("baseName is null.");
87 throw new ArgumentNullException ("assembly is null.");
89 BaseNameField = baseName;
90 MainAssembly = assembly;
91 resourceSetType = CheckResourceSetType(usingResourceSet);
92 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
95 /* Private constructor for CreateFileBasedResourceManager */
96 private ResourceManager(String baseName, String resourceDir, Type usingResourceSet) : this()
99 throw new ArgumentNullException("The base name is null");
101 if(baseName.EndsWith(".resources")) {
102 throw new ArgumentException("The base name ends in '.resources'");
104 if(resourceDir==null) {
105 throw new ArgumentNullException("The resourceDir is null");
108 BaseNameField = baseName;
110 resourceSetType = CheckResourceSetType(usingResourceSet);
111 this.resourceDir = resourceDir;
114 public static ResourceManager CreateFileBasedResourceManager (string baseName,
115 string resourceDir, Type usingResourceSet)
117 return new ResourceManager(baseName, resourceDir, usingResourceSet);
120 public virtual string BaseName
122 get { return BaseNameField; }
125 public virtual bool IgnoreCase
127 get { return ignoreCase; }
128 set { ignoreCase = value; }
131 public virtual Type ResourceSetType
133 get { return resourceSetType; }
136 public virtual object GetObject(string name)
138 return(GetObject(name, null));
141 public virtual object GetObject(string name, CultureInfo culture)
144 throw new ArgumentNullException("name is null");
148 culture=CultureInfo.CurrentUICulture;
152 ResourceSet set=InternalGetResourceSet(culture, true, true);
156 obj=set.GetObject(name, ignoreCase);
162 /* Try parent cultures */
165 culture=culture.Parent;
167 set=InternalGetResourceSet(culture, true, true);
169 obj=set.GetObject(name, ignoreCase);
174 } while(!culture.Equals(neutral_culture) &&
175 !culture.Equals(CultureInfo.InvariantCulture));
182 public virtual ResourceSet GetResourceSet (CultureInfo culture,
183 bool createIfNotExists, bool tryParents)
186 if (culture == null) {
187 throw new ArgumentNullException ("CultureInfo is a null reference.");
191 return(InternalGetResourceSet(culture, createIfNotExists, tryParents));
195 public virtual string GetString (string name)
197 return(GetString(name, null));
200 public virtual string GetString (string name, CultureInfo culture)
203 throw new ArgumentNullException ("Name is null.");
207 culture=CultureInfo.CurrentUICulture;
211 ResourceSet set=InternalGetResourceSet(culture, true, true);
215 str=set.GetString(name, ignoreCase);
221 /* Try parent cultures */
224 culture=culture.Parent;
226 set=InternalGetResourceSet(culture, true, true);
228 str=set.GetString(name, ignoreCase);
233 } while(!culture.Equals(neutral_culture) &&
234 !culture.Equals(CultureInfo.InvariantCulture));
240 protected virtual string GetResourceFileName (CultureInfo culture)
242 if(culture.Equals(CultureInfo.InvariantCulture)) {
243 return(BaseNameField + ".resources");
245 return(BaseNameField + "." + culture.Name + ".resources");
249 protected virtual ResourceSet InternalGetResourceSet (CultureInfo culture, bool Createifnotexists, bool tryParents)
253 if (culture == null) {
254 string msg = String.Format ("Could not find any resource appropiate for the " +
255 "specified culture or its parents (assembly:{0})",
256 MainAssembly != null ? MainAssembly.GetName ().Name : "");
258 throw new MissingManifestResourceException (msg);
260 /* if we already have this resource set, return it */
261 set=(ResourceSet)ResourceSets[culture];
266 if(MainAssembly != null) {
267 /* Assembly resources */
269 string filename=GetResourceFileName(culture);
271 stream=MainAssembly.GetManifestResourceStream(filename);
273 /* Try a satellite assembly */
274 Version sat_version=GetSatelliteContractVersion(MainAssembly);
277 a = MainAssembly.GetSatelliteAssembly (culture, sat_version);
278 stream=a.GetManifestResourceStream(filename);
279 } catch (Exception) {} // Ignored
282 if(stream!=null && Createifnotexists==true) {
283 object[] args=new Object[1];
288 * MissingMethodException, or
289 * just let someone else deal
292 set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
293 } else if (culture == CultureInfo.InvariantCulture) {
294 string msg = "Could not find any resource appropiate for the " +
295 "specified culture or its parents (assembly:{0})";
297 msg = String.Format (msg, MainAssembly != null ? MainAssembly.GetName ().Name : "");
299 throw new MissingManifestResourceException (msg);
301 } else if(resourceDir != null) {
303 string filename=Path.Combine(resourceDir, this.GetResourceFileName(culture));
304 if(File.Exists(filename) &&
305 Createifnotexists==true) {
306 object[] args=new Object[1];
311 * MissingMethodException, or
312 * just let someone else deal
315 set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
319 if(set==null && tryParents==true) {
320 set=this.InternalGetResourceSet(culture.Parent, Createifnotexists, tryParents);
324 ResourceSets.Add(culture, set);
330 public virtual void ReleaseAllResources ()
334 foreach (ResourceSet r in ResourceSets)
336 ResourceSets.Clear();
340 protected static CultureInfo GetNeutralResourcesLanguage (Assembly a)
344 attrs=a.GetCustomAttributes(typeof(NeutralResourcesLanguageAttribute), false);
346 if(attrs.Length==0) {
347 return(CultureInfo.InvariantCulture);
349 NeutralResourcesLanguageAttribute res_attr=(NeutralResourcesLanguageAttribute)attrs[0];
351 return(new CultureInfo(res_attr.CultureName));
355 protected static Version GetSatelliteContractVersion (Assembly a)
359 attrs=a.GetCustomAttributes(typeof(SatelliteContractVersionAttribute), false);
361 if(attrs.Length==0) {
364 SatelliteContractVersionAttribute sat_attr=(SatelliteContractVersionAttribute)attrs[0];
366 /* Version(string) can throw
367 * ArgumentException if the version is
368 * invalid, but the spec for
369 * GetSatelliteContractVersion says we
370 * can throw the same exception for
371 * the same reason, so dont bother to
374 return(new Version(sat_attr.Version));