C # - не удается получить строку из ResourceManager (из спутниковой сборки) - PullRequest
3 голосов
/ 09 марта 2011

Я разрабатываю локализуемое приложение.В моем «локальном» файле ресурсов я использую язык, используемый по умолчанию (английский), и, если возможно, я загружаю предпочтения и культуру пользователя и загружаю строки, переведенные на это язык.

Итак, что я сделал:

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 ]

9 голосов
/ 09 марта 2011

Я нашел, почему, надеюсь, это поможет кому-то, что находится в том же случае.

Итак, я посмотрел в 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);
2 голосов
/ 09 марта 2011

Из службы поддержки Microsoft:

Эта проблема возникает, если вы используете локализованный ресурс, который существует в сателлитной сборке, созданной вами с использованием файла .resources с неправильным именем файла.Эта проблема обычно возникает, если вы вручную создаете вспомогательную сборку:

Попробуйте этот KB:

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

0 голосов
/ 10 июня 2016

Альтернативный подход, введите в качестве кода теста следующее:

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

При отладке проверьте содержимое ресурсов, чтобы увидеть, соответствует ли оно тому, что вы загружаете с ResourceManager.

Особенно обратите внимание: если вы получите что-то вроде 'MyAssembly..Resources.resources', то вам нужно будет явно добавить 'Resources' в конструктор ResourceManager:

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