C# - 无法从 ResourceManager 获取字符串(来自附属程序集)
Posted
技术标签:
【中文标题】C# - 无法从 ResourceManager 获取字符串(来自附属程序集)【英文标题】:C# - Cannot getting a string from ResourceManager (from satellite assembly) 【发布时间】:2011-03-09 13:38:31 【问题描述】:我正在开发一个可本地化的应用程序。在我的“本地”资源文件中,我有默认使用的语言(英语),如果可能,我会加载用户的偏好和文化,并加载翻译成语言的字符串。
所以我做了什么:
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
,有人能告诉我为什么吗?
谢谢!
[编辑]
项目“我的应用程序”
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);
我不明白...
【问题讨论】:
您确定该资源存在于资源程序集中吗? 异常相关的错误信息是什么?以下问题和答案可能会对您有所帮助:***.com/questions/1327692/… 是的,我敢肯定,当我使用 Enumerator 在其中循环时,我会得到我放入卫星资源文件中的所有字符串。 @"Mr. Disappointment" : 已经看了,不行。 @Arnaud:Dang,这个怎么样(我认为它最终归结为命名空间问题):jameswho.blogspot.com/2004/06/… 【参考方案1】:我找到了原因,希望这对遇到同样情况的人有所帮助。
所以,我查看了 MyApp_FR.dll 生成使用资源文件的代码,它是:
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);
【讨论】:
我反编译了处理这个问题的 .NET 代码,它在加载之前任意附加了.resources
。甚至从 VS 生成的附属程序集也会失败。所以我认为.NET 处理附属程序集的方式还有改进的余地。感谢您的侦探工作。【参考方案2】:
来自微软支持:
如果您使用存在于附属程序集中的本地化资源,则会出现此问题,该资源是通过使用具有不适当文件名的 .resources 文件创建的。如果您手动创建附属程序集,通常会出现此问题:
试试这个知识库:
http://support.microsoft.com/kb/839861
【讨论】:
不是手动创建的文件。我在 VS2k8 中创建了一个新项目,进入“属性”->“资源”->“添加”并将我所有的翻译都放在这里。【参考方案3】:另一种方法,将以下代码作为测试代码:
string[] resources =
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
在调试时,检查资源的内容,看看它是否与您使用 ResourceManager 加载的内容相匹配。
特别注意,如果你得到类似“MyAssembly..Resources.resources”的东西,那么你需要显式地将“Resources”添加到 ResourceManager 构造函数中:
private static readonly ResourceManager stringTable =
new ResourceManager("MyAssembly.Resources", Assembly.GetExecutingAssembly());
【讨论】:
以上是关于C# - 无法从 ResourceManager 获取字符串(来自附属程序集)的主要内容,如果未能解决你的问题,请参考以下文章
Hadoop Nodemanager 和 Resourcemanager 未启动
根据字符串从资源中取出对应的资源ResourceManager.GetObject
FlinkFlink Cannot serve slot request, no ResourceManager connected Adding as pending request