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);
}
}
}
Я не понимаю...
3 ответа
Я нашел, почему, надеюсь, это поможет кому-то, кто находится в том же случае.
Итак, я посмотрел в 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);
Из службы поддержки Microsoft:
Эта проблема возникает, если вы используете локализованный ресурс, который существует в сателлитной сборке, созданной вами с использованием файла.resources с неправильным именем файла. Эта проблема обычно возникает, если вы вручную создаете вспомогательную сборку:
Попробуйте это KB:
Альтернативный подход, добавьте следующее в качестве тестового кода:
string[] resources =
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
При отладке проверьте содержимое ресурсов, чтобы увидеть, соответствует ли оно тому, что вы загружаете с ResourceManager.
Особенно обратите внимание, что если вы получаете что-то вроде "MyAssembly..Resources.resources", то вам необходимо явно добавить "Resources" в конструктор ResourceManager:
private static readonly ResourceManager stringTable =
new ResourceManager("MyAssembly.Resources", Assembly.GetExecutingAssembly());