我有一个简单的Windows窗体(C#,. NET 2.0)应用程序,使用Visual Studio 2008构建.
我想支持多种UI语言,并使用表单的"Localizable"属性和特定于文化的.resx文件,本地化方面可以无缝轻松地工作.Visual Studio会自动将特定于文化的resx文件编译为附属程序集,因此在我编译的应用程序文件夹中,存在包含这些附属程序集的特定于文化的子文件夹.
我希望将应用程序部署(复制到位)作为单个程序集,但仍保留包含多组特定于文化的资源的能力.
使用ILMerge(或ILRepack),我可以将附属程序集合并到主可执行程序集中,但标准的.NET ResourceManager回退机制找不到编译到主程序集中的特定于文化的资源.
有趣的是,如果我采用我的合并(可执行)程序集并将其副本放入特定于文化的子文件夹中,那么一切正常!同样,当我使用Reflector(或ILSpy)时,我可以在合并的组合中看到主要和特定于文化的资源.但是将主程序集复制到特定于文化的子文件夹中无论如何都会破坏合并的目的 - 我真的需要只有一个单一程序集的副本......
我想知道是否有任何方法可以劫持或影响ResourceManager回退机制,以在同一个程序集中查找特定于文化的资源,而不是在GAC和文化命名的子文件夹中查找.我看到了以下文章中描述的回退机制,但没有关于它如何被修改的线索:BCL团队关于ResourceManager的博客文章.
有谁有想法吗?这似乎是一个相对常见的在线问题(例如,Stack Overflow上的另一个问题:" ILMerge和本地化资源程序集 "),但我没有在任何地方找到任何权威答案.
按照下面的casperOne的建议,我终于能够做到这一点.
我在这里提出解决方案代码,因为casperOne提供了唯一的答案,我不想添加自己的答案.
通过从"InternalGetResourceSet"方法中实现的Framework资源查找回退机制中拉出内容并使我们的同一组件搜索成为第一个使用的机制,我能够使它工作.如果在当前程序集中找不到资源,那么我们调用基本方法来启动默认搜索机制(感谢下面的@Wouter注释).
为此,我派生了"ComponentResourceManager"类,并且只覆盖了一个方法(并重新实现了一个私有框架方法):
class SingleAssemblyComponentResourceManager :
System.ComponentModel.ComponentResourceManager
{
private Type _contextTypeInfo;
private CultureInfo _neutralResourcesCulture;
public SingleAssemblyComponentResourceManager(Type t)
: base(t)
{
_contextTypeInfo = t;
}
protected override ResourceSet InternalGetResourceSet(CultureInfo culture,
bool createIfNotExists, bool tryParents)
{
ResourceSet rs = (ResourceSet)this.ResourceSets[culture];
if (rs == null) …Run Code Online (Sandbox Code Playgroud) 我正在使用ILMerge从包含1个exe和2个资源dll的项目中创建单个程序集应用程序:
这是一个简单的测试项目,有1个表单(Form1.cs),所以没什么特别的.我的目标是使用工作资源管理器创建一个单独的程序集应用程序(我已阅读ILMerge和本地化资源程序集以及单程序集多语言Windows窗体部署(ILMerge和附属程序集/本地化) - 可能吗?有关如何执行的信息这个).
编译项目后,我使用以下命令行参数运行ILMerge:
ilmerge /log:test.txt /target:winexe /copyattrs /allowdup /out:test_merged.exe
"C:\projectdir\bin\Debug\test.exe" "C:\projectdir\bin\Debug\fr-FR\test.resources.dll"
"C:\projectdir\bin\Debug\nl-BE\test.resources.dll"
Run Code Online (Sandbox Code Playgroud)
如果我使用Reflector检查合并程序集的内容,我在资源树节点下看到以下内容:
而不是fr-FR和nl-BE资源,我有2倍的fr-FR资源.这是因为资源dll的名称相同吗?结果是我只能在运行时获取fr-FR资源.
有任何想法吗 ?
更新(日志文件内容):(注意:二进制文件以"loc_"为前缀,为了清楚起见,我在之前的帖子中将它们删除了)
ILMerge version 2.10.526.0
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved.
ILMerge /log:loc_test.txt /target:winexe /copyattrs /allowdup /out:loc_test_merged.exe c:\Users\<user>\Documents\Visual Studio 2008\Projects\loc_test\loc_test\bin\Debug\loc_test.exe C:\Users\<user>\Documents\Visual Studio 2008\Projects\loc_test\loc_test\bin\Debug\fr-FR\loc_test.resources.dll C:\Users\<user>\Documents\Visual Studio 2008\Projects\loc_test\loc_test\bin\Debug\nl-BE\loc_test.resources.dll
Set platform to 'v2', using directory 'C:\Windows\Microsoft.NET\Framework\v2.0.50727\..\v2.0.50727' for mscorlib.dll
Running on Microsoft (R) .NET Framework …Run Code Online (Sandbox Code Playgroud)