System.argumentNullexception в ResourceManager.EtString Internals
-
29-09-2019 - |
Вопрос
Мой код:
System.Resources.ResourceManager resourceManager = GetResourceManager();
string str = resourceManager.GetString("delete", new CultureInfo(1033));
В текущем проекте скомпилирован под .NET 2.0 Все работает как исключено. Переменная ул Содержит строку ресурса для 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.internalgetResourset. которые вызывают звонок Монитор .enter. с нулевым объектом. Но я называю методом Уточнять с не нулевыми параметрами GetString («Удалить», новый CultureInfo (1033)).
Эта ошибка, кажется, похожа на System.argumentNullexception в System.Threading.monitor.enter.. Отказ Может быть, некоторая ошибка в Monitor.enter, или что-то еще?
Обновление: когда я смотрю в отладчик на объекте resourceManager.ResourceSets.Items[2].Value.Table["delete"]
Затем он содержит строковое значение «Удалить». Элементы недвижимости [2] Здесь указывая на LCID 1033. Это означает, что Manager Resource уже содержит локализованную строку для ключа ресурсов удалять на языке 1033. Отказ Кто-нибудь знает, где может быть ошибка?
Решение
Я также думаю, что вы должны объявить и использовать свой собственный словарь для хранения, поскольку ресурсы помечены как устаревшие под .NET 4.0
Другие советы
Я нашел ответ на себя. Вот детали: у нас есть пользовательская реализация 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. Я думаю, что проблема находится в ParamEmerless Constructor, который в .NET 2.0 Инстанционное частное поле. Это ._Resourcesets (который позже используется в InternetgetResourceset. для монитора .enter). Но в .NET 4.0 Конструктор Parameterless не содержит частное поле Это ._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;
}
}
}
«Магия» вот что я должен перезаписать метод InternetgetResourceset. Чтобы загрузить свои ресурсы из пользовательских хранилищ (БД) и вернуть обратно «ресурсы» для указанной культуры. Теперь это работает как очарование.