Как получить местоположение спутниковой сборки текущей культуры?

Мое приложение C#/WF использует несколько файлов, которые различаются для разных языков. Эти файлы не могут размещаться в качестве ресурсов во вспомогательных сборках. Однако я хочу поместить их в те же каталоги, что и вспомогательные сборки, но мне нужно знать, где на самом деле находится сборка (включая ситуацию, когда используется язык по умолчанию, встроенный в двоичный файл).

Например, когда приложение автоматически переключается на польский язык, я хочу восстановить местоположение:

D:\‹папка приложения›\pl-PL\

Есть ли способ сделать это? Обратите внимание, что я хочу получить эту информацию из сборки, а не угадывая местоположение папки.


С помощью Steve B вот решение:

string FindSatelliteAssemblyLocation(CultureInfo culture)
{
    if (culture == CultureInfo.InvariantCulture)
        return Path.GetDirectoryName(Application.ExecutablePath);

    try
    {
        Uri location = new Uri(Assembly.GetExecutingAssembly().GetSatelliteAssembly(culture).CodeBase);
        return Path.GetDirectoryName(location.LocalPath);
    }
    catch
    {
        return FindSatelliteAssemblyLocation(culture.Parent);
    }
}

person Spook    schedule 06.11.2012    source источник


Ответы (2)


Вы можете использовать текущую культуру пользовательского интерфейса потока, чтобы получить язык:

var subfolder = System.Threading.Thread.CurrentUICulture.Name;
person Steve B    schedule 06.11.2012
comment
Кажется, у нас с вами схожие подходы, но вы используете CurrentUICulture, а я просто предлагаю CurrentCulture. Знаете ли вы, в чем именно отличия каждого из них? - person red_sky; 06.11.2012
comment
Прочтите документацию. В нем указано, что CurrentCulture — это культура потока (не знаю, что это значит), где CurrentUICulture — это культура, используемая при просмотре локализованных ресурсов. Это то, о чем спрашивает оп. - person Steve B; 06.11.2012
comment
Я действительно это читал. Однако оба исходят из текущего потока (например, каждый поток имеет свои собственные CurrentCulture и CurrentUICulture), поэтому я не уверен, в чем разница. Я знаю, что CurrentCulture основан на локализации, установленной на самой машине, но я не понимаю, чем она должна отличаться от локализации пользовательского интерфейса (которая также определяется пользователем). - person red_sky; 06.11.2012
comment
Я нашел окончательный ответ: stackoverflow.com/a/329041/821132 Я обновлю свой ответ. - person red_sky; 06.11.2012
comment
Да, но он уязвим в ситуации, когда, например, локализованная сборка находится в папке pl, а локаль потока - pl-PL. Попытка загрузить вспомогательную сборку локали потока завершится ошибкой. - person Spook; 06.11.2012
comment
@Spook: вы можете положиться на CultureInfo.Parent, чтобы обеспечить резервное поведение, такое же, как и стандартное управление ресурсами. Во-первых, попробуйте pl-pl, если не найдено, попробуйте pl, если не найдено, попробуйте «нейтральный». НЕ сложно реализовать, я считаю. - person Steve B; 07.11.2012
comment
Хорошо, теперь я могу написать полную функцию. Спасибо! - person Spook; 08.11.2012

Я чувствую, что вы могли бы использовать комбинацию System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) и CultureInfo.CurrentUICulture, чтобы понять это.

Например, если ваша сборка находится в папке C:\Program Files\MyCompany\App\, а текущая культура пользовательского интерфейса — en_US, вы можете объединить их:

string exeDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
string culture = CultureInfo.CurrentUICulture.Name;

string langDir = System.IO.Path.Combine(exeDir, culture);

Для создания "C:\Program Files\MyCompany\App\en_US"

person red_sky    schedule 06.11.2012
comment
Я бы использовал Path.Combine вместо string.join. Это более явное его использование. - person Steve B; 06.11.2012
comment
Эх... Обратите внимание, что я хочу получить эту информацию из сборки, а не угадывая расположение папки. - person Spook; 06.11.2012
comment
Спук, я не понимаю, о чем ты говоришь? Это ничего не угадывает. Он получает все это из текущей сборки. Кроме того, Стив, я обновлю свой ответ. - person red_sky; 06.11.2012
comment
Под угадыванием я подразумеваю объединение пути приложения и имени культуры. AFAIR расположение спутниковых сборок может быть изменено, и тогда этот метод будет бесполезен. - person Spook; 06.11.2012
comment
Учитывая, что код, который я предоставил, получает расположение папки любой сборки, которую вы запускаете, а затем добавляет культуру, как это может быть неправильно? Я действительно не могу понять проблему здесь, так как это прекрасно делает то, что вы хотите получить. Из того, что я знаю о вспомогательных сборках, в них нет никакого исполняемого кода, только ресурсы, поэтому в какой-то момент вам все равно придется запускать основной исполняемый файл. Почему расположение спутников изменилось? - person red_sky; 06.11.2012
comment
Прочитав msdn.microsoft.com/en-us /library/21a15yht(v=vs.100).aspx, я не вижу никаких проблем с этим решением. Вспомогательные сборки всегда будут находиться в каталоге вашего основного исполняемого файла. - person red_sky; 06.11.2012
comment
Например, если они не в GAC. Решение с добавлением имени культуры в папку приложения во многих ситуациях не работает. Предположим, например, что локаль системы — польский (Польша) (pl-PL), а локализация помещена в польскую папку (pl). Программа будет правильно локализована, но попытка угадать путь путем применения локали пользовательского интерфейса к пути программы вернет несуществующую папку. Кстати, мое решение тоже не сработает (мне нужно отредактировать свой ответ). - person Spook; 06.11.2012
comment
Локализация никогда не должна ограничиваться только языком. Он всегда должен иметь национальный компонент. Например, мексиканский испанский отличается от испанского (или канадский французский от французского французского). Вы должны использовать их для именования папок, а не только языка. См.: msdn.microsoft.com/en-us/library/21a15yht.aspx Ресурсы подраздела в глобальном кэше сборок #8 - person red_sky; 06.11.2012