C# – 无法从ResourceManager获取字符串(来自附属程序集)

我正在开发一个可本地化的应用程序。 在我的“本地”资源文件中,我使用了默认使用的语言(英语),如果可能的话,我加载用户的首选项和文化,并加载翻译成语言的字符串。

所以我做了什么:

private static CultureInfo _culture = CultureInfo.CurrentUICulture; private static ResourceManager _manager; private static void ToNeutralCulture() { while (!_culture.IsNeutralCulture) { _culture = _culture.Parent; } } private static void LoadCulture() { ResourceManager manager = Properties.Resources.ResourceManager; try { ToNeutralCulture(); string assembly = Assembly.GetCallingAssembly().GetName().CodeBase; string assemblyDir = Path.GetDirectoryName(assembly); string assemblyName = Path.GetFileNameWithoutExtension(assembly); string resourceFileName = string.Format(CultureInfo.InvariantCulture, @"{0}\{1}_{2}.dll", assemblyDir, assemblyName, _culture.Name.ToUpper()); FileInfo resourceFile = new FileInfo(resourceFileName); if (resourceFile.Exists) { Assembly resourceAssembly = Assembly.LoadFrom(resourceFile.FullName); string[] manifests = resourceAssembly.GetManifestResourceNames(); if (manifests.Length == 1) { manager = new ResourceManager(manifests[0], resourceAssembly); } using (ResourceReader reader = new ResourceReader(resourceAssembly.GetManifestResourceStream(manifests[0]))) { IDictionaryEnumerator dict = reader.GetEnumerator(); while (dict.MoveNext()) { string key = dict.Key as string; object val = dict.Value; //string mVal = manager.GetString(key); } } } } catch (Exception ex) { Trace.WriteLine(ex.Message); Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Fail to loading culture {0}", (_culture == null) ? "--" : _culture.EnglishName)); } _manager = manager; } 

正确加载程序集,枚举器将显示资源文件中存在的所有资源,工作正常,除了:

 string mVal = manager.GetString(key); 

当我取消注释这一行时,我有一个System.Resources.MissingManifestResourceException ,有人可以告诉我为什么吗?

谢谢 !


[编辑]

项目“MyApp”

 namespace MyApp { Assembly resourceAssembly = Assembly.LoadFrom(resourceFileName); string[] manifests = resourceAssembly.GetManifestResourceNames(); if (manifests.Length == 1) { manager = new ResourceManager(manifests[0], resourceAssembly); } // Throws the exception manager.GetString("PleaseCallIT", null); // Works using (ResourceReader reader = new ResourceReader(resourceAssembly.GetManifestResourceStream(manifests[0]))) { IDictionaryEnumerator dict = reader.GetEnumerator(); while (dict.MoveNext()) { string key = dict.key as string; // PleaseCallIT object val = dict.value; // Please call IT. } } } 

项目“MyApp_FR”(Resources.Designer.cs自动生成的文件)

 namespace MyApp.Properties { // ... internal static string PleaseCallIT { get { return ResourceManager.GetString("PleaseCallIT", resourceCulture); } } } 

我不明白……

我找到了原因,希望这能帮助那些处于相同情况的人。

所以,我在MyApp_FR.dll查看了使用Resource文件生成的代码,它是:

 new global::System.Resources.ResourceManager("MyApp_FR.Properties.Resources", typeof(Resources).Assembly); 

但是当检索清单文件名时,我得到了:

“MyApp_FR.Properties.Resources.resources”

似乎在这个房间里有很多.resource …通过删除它,我可以正常使用我的ResourceManager,一切正常……

最终代码:

 Assembly resourceAssembly = Assembly.LoadFrom(resourceFileName); string[] manifests = resourceAssembly.GetManifestResourceNames(); if (manifests.Length == 1) { string manifest = manifests[0].Replace(".resources", string.Empty); manager = new ResourceManager(manifest, resourceAssembly); } // Works ! manager.GetString("PleaseCallIT", null); 

来自Microsoft支持:

如果您使用通过使用具有不适当的文件名的.resources文件创建的附属程序集中存在的本地化资源,则会出现此问题。 如果手动创建附属程序集通常会发生此问题:

试试这个KB:

http://support.microsoft.com/kb/839861

另一种方法,将以下内容作为测试代码:

 string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); 

在调试中,检查资源的内容以查看它是否与您使用ResourceManager加载的内容相匹配。

特别要注意的是,如果你得到类似’MyAssembly..Resources.resources’的东西,那么你需要向ResourceManager构造函数显式添加’Resources’:

  private static readonly ResourceManager stringTable = new ResourceManager("MyAssembly.Resources", Assembly.GetExecutingAssembly());