System.ArgumentNullException в ResourceManager.GetString внутренности - PullRequest
1 голос
/ 01 декабря 2010

Мой код:

System.Resources.ResourceManager resourceManager = GetResourceManager();
string str = resourceManager.GetString("delete", new CultureInfo(1033));

В текущем проекте, скомпилированном в .NET 2.0, все работает как исключено. Переменная str содержит строку ресурса для LCID 1033 - Удалить , это нормально.

Сейчас мы обновляем систему до .NET 4.0, перекомпилированный проект под целевой платформой .NET 4.0. Теперь скомпилированный как сборки .NET 4.0, он генерирует исключение System.ArgumentNullException с сообщением Значение не может быть нулевым. . Трассировка стека:

   at System.Threading.Monitor.Enter(Object obj)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)

Интересно, что здесь находится трассировка стека, где он указывает на метод внутренней структуры в ResourceManager.InternalGetResourceSet , который вызывает Monitor.Enter с нулевым объектом. Но я вызываю метод GetString с ненулевыми параметрами GetString ("delete", new CultureInfo (1033)) .

Эта ошибка похожа на System.ArgumentNullException в System.Threading.Monitor.Enter . Может быть, какая-то ошибка в Monitor.Enter или что-то еще?

Обновление: Когда я смотрю в отладчике на объект resourceManager.ResourceSets.Items[2].Value.Table["delete"], то он содержит строковое значение «Удалить». свойство Items [2] здесь указывает на LCID 1033. Это означает, что менеджер ресурсов уже содержит локализованную строку для ключа ресурса delete на языке 1033 . Кто-нибудь знает, где может быть ошибка?

Ответы [ 2 ]

1 голос
/ 29 мая 2011

Я также думаю, что вы должны объявить и использовать свой собственный словарь для хранения, поскольку ResourceSets помечен как устаревший в .NET 4.0

1 голос
/ 01 декабря 2010

Я нашел ответ сам.Вот подробности: У нас есть пользовательская реализация ResourceManager, например:

public class DatabaseResourceManager : System.Resources.ResourceManager 
{
  public DatabaseResourceManager(int applicationID, string bundle) 
  {
    foreach (int languageID in ResourceProvider.Provider.GetLanguages(applicationID))
    {
      DatabaseResourceReader r = new DatabaseResourceReader(applicationID, bundle, languageID);
      ResourceSets.Add(new CultureInfo(languageID), new ResourceSet(r));
    }
}

В .NET 2.0 это работает хорошо, но в .NET 4.0 что-то изменилось в реализации ResourceManager. Я думаю, что проблема заключается в отсутствии параметровконструктор, который в .NET 2.0 создает частное поле this._resourceSets (которое впоследствии используется в InternalGetResourceSet для Monitor.Enter).Но в .NET 4.0 конструктор без параметров не создает частное поле this._resourceSets и, таким образом, он завершается ошибкой позже (как описано выше).

Я должен переписать свой собственный менеджер ресурсов, чтобы это работало:

public class DatabaseResourceManager : System.Resources.ResourceManager 
{
  public DatabaseResourceManager(int applicationID, string bundle) 
  {
    ResourceSets = new Hashtable();
    this.applicationID = applicationID;
    this.bundle = bundle;
  }

  protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
  {
    if (this.ResourceSets.Contains(culture.Name))
        return this.ResourceSets[culture.Name] as ResourceSet;

    lock (syncLock)
    {
        if (this.ResourceSets.Contains(culture.Name))
            return this.ResourceSets[culture.Name] as ResourceSet;

        DatabaseResourceReader r = new DatabaseResourceReader(applicationID, bundle, culture.LCID);
        ResourceSet rs = new ResourceSet(r);

        this.ResourceSets.Add(culture.Name, rs);

        return rs;
    }
  }
}

«Волшебство» заключается в том, что я должен перезаписать метод InternalGetResourceSet , чтобы загрузить мои ресурсы из пользовательского хранилища (БД) и вернуть обратно «ResourceSet» для указанной культуры.Теперь это работает как шарм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...