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;
52 resourceSetType = resourceSource;
53 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
56 public ResourceManager (string baseName, Assembly assembly) : this()
59 throw new ArgumentNullException ("baseName is null.");
61 throw new ArgumentNullException ("assembly is null.");
63 BaseNameField = baseName;
64 MainAssembly = assembly;
65 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
68 private Type CheckResourceSetType(Type usingResourceSet)
70 if(usingResourceSet==null) {
71 return(typeof(ResourceSet));
73 if (!usingResourceSet.IsSubclassOf (typeof (ResourceSet)))
74 throw new ArgumentException ("Type must be from ResourceSet.");
76 return(usingResourceSet);
80 public ResourceManager (string baseName, Assembly assembly, Type usingResourceSet) : this()
83 throw new ArgumentNullException ("baseName is null.");
85 throw new ArgumentNullException ("assembly is null.");
87 BaseNameField = baseName;
88 MainAssembly = assembly;
89 resourceSetType = CheckResourceSetType(usingResourceSet);
90 neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
93 /* Private constructor for CreateFileBasedResourceManager */
94 private ResourceManager(String baseName, String resourceDir, Type usingResourceSet) : this()
97 throw new ArgumentNullException("The base name is null");
99 if(baseName.EndsWith(".resources")) {
100 throw new ArgumentException("The base name ends in '.resources'");
102 if(resourceDir==null) {
103 throw new ArgumentNullException("The resourceDir is null");
106 BaseNameField = baseName;
108 resourceSetType = CheckResourceSetType(usingResourceSet);
109 this.resourceDir = resourceDir;
112 public static ResourceManager CreateFileBasedResourceManager (string baseName,
113 string resourceDir, Type usingResourceSet)
115 return new ResourceManager(baseName, resourceDir, usingResourceSet);
118 public virtual string BaseName
120 get { return BaseNameField; }
123 public virtual bool IgnoreCase
125 get { return ignoreCase; }
126 set { ignoreCase = value; }
129 public virtual Type ResourceSetType
131 get { return resourceSetType; }
134 public virtual object GetObject(string name)
136 return(GetObject(name, null));
139 public virtual object GetObject(string name, CultureInfo culture)
142 throw new ArgumentNullException("name is null");
146 culture=CultureInfo.CurrentUICulture;
150 ResourceSet set=InternalGetResourceSet(culture, true, true);
154 obj=set.GetObject(name, ignoreCase);
160 /* Try parent cultures */
163 culture=culture.Parent;
165 set=InternalGetResourceSet(culture, true, true);
167 obj=set.GetObject(name, ignoreCase);
172 } while(!culture.Equals(neutral_culture) &&
173 !culture.Equals(CultureInfo.InvariantCulture));
180 public virtual ResourceSet GetResourceSet (CultureInfo culture,
181 bool createIfNotExists, bool tryParents)
184 if (culture == null) {
185 throw new ArgumentNullException ("CultureInfo is a null reference.");
189 return(InternalGetResourceSet(culture, createIfNotExists, tryParents));
193 public virtual string GetString (string name)
195 return(GetString(name, null));
198 public virtual string GetString (string name, CultureInfo culture)
201 throw new ArgumentNullException ("Name is null.");
205 culture=CultureInfo.CurrentUICulture;
209 ResourceSet set=InternalGetResourceSet(culture, true, true);
213 str=set.GetString(name, ignoreCase);
219 /* Try parent cultures */
222 culture=culture.Parent;
224 set=InternalGetResourceSet(culture, true, true);
226 str=set.GetString(name, ignoreCase);
231 } while(!culture.Equals(neutral_culture) &&
232 !culture.Equals(CultureInfo.InvariantCulture));
238 protected virtual string GetResourceFileName (CultureInfo culture)
240 if(culture.Equals(CultureInfo.InvariantCulture)) {
241 return(BaseNameField + ".resources");
243 return(BaseNameField + "." + culture.Name + ".resources");
247 protected virtual ResourceSet InternalGetResourceSet (CultureInfo culture, bool Createifnotexists, bool tryParents)
251 /* if we already have this resource set, return it */
252 set=(ResourceSet)ResourceSets[culture];
257 if(MainAssembly != null) {
258 /* Assembly resources */
260 string filename=GetResourceFileName(culture);
262 stream=MainAssembly.GetManifestResourceStream(filename);
264 /* Try a satellite assembly */
265 /* Commented out. It's not implemented yet
266 Version sat_version=GetSatelliteContractVersion(MainAssembly);
267 Assembly a=MainAssembly.GetSatelliteAssembly(culture, sat_version);
268 stream=a.GetManifestResourceStream(filename);
272 if(stream!=null && Createifnotexists==true) {
273 object[] args=new Object[1];
278 * MissingMethodException, or
279 * just let someone else deal
282 set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
284 } else if(resourceDir != null) {
286 string filename=Path.Combine(resourceDir, this.GetResourceFileName(culture));
287 if(File.Exists(filename) &&
288 Createifnotexists==true) {
289 object[] args=new Object[1];
294 * MissingMethodException, or
295 * just let someone else deal
298 set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
302 if(set==null && tryParents==true) {
303 set=this.InternalGetResourceSet(culture.Parent, Createifnotexists, tryParents);
307 ResourceSets.Add(culture, set);
313 public virtual void ReleaseAllResources ()
317 foreach (ResourceSet r in ResourceSets)
319 ResourceSets.Clear();
323 protected static CultureInfo GetNeutralResourcesLanguage (Assembly a)
327 attrs=a.GetCustomAttributes(typeof(NeutralResourcesLanguageAttribute), false);
329 if(attrs.Length==0) {
330 return(CultureInfo.InvariantCulture);
332 NeutralResourcesLanguageAttribute res_attr=(NeutralResourcesLanguageAttribute)attrs[0];
334 return(new CultureInfo(res_attr.CultureName));
338 protected static Version GetSatelliteContractVersion (Assembly a)
342 attrs=a.GetCustomAttributes(typeof(SatelliteContractVersionAttribute), false);
344 if(attrs.Length==0) {
347 SatelliteContractVersionAttribute sat_attr=(SatelliteContractVersionAttribute)attrs[0];
349 /* Version(string) can throw
350 * ArgumentException if the version is
351 * invalid, but the spec for
352 * GetSatelliteContractVersion says we
353 * can throw the same exception for
354 * the same reason, so dont bother to
357 return(new Version(sat_attr.Version));