C# - повторно инициализировать статический класс?
У меня есть класс в веб-приложении, над которым я работаю, который содержит настройки клиента. Для некоторого фона я не владею этим классом, и изменение его не является вариантом. Недавно мы добавили логику для хранения настроек в базе данных,и мне было поручено создать страницу для их редактирования.
вот моя проблема; настройки хранятся в статическом классе и сами являются статическими свойствами только для чтения. Например
public static class Settings
{
public static readonly setting1 = SettingmanagerClass.GetSetting("setting1");
public static readonly setting2 = SettingmanagerClass.GetSetting("setting2");
public static readonly setting3 = SettingmanagerClass.GetSetting("setting3");
}
теперь, например, через страница, которую я написал, Мы меняем значение для setting2 на" Happy Variable"; он сохраняет в БД просто отлично, но теперь мне нужно, чтобы он отражался в веб-приложении как новое значение. Поскольку это статическое свойство readonly статического класса, оно вызывается только тогда, когда приложение сначала подключается и не может быть установлено вручную.
чтобы повторить, я не владею исходным классом, поэтому "просто сделать свойства записываемыми" не является (в настоящее время) допустимым вариантом. Обычно я просто обсуждаю это со своим боссом. и он мог бы принять решение и, возможно, позволить мне изменить другой класс, но я не в состоянии сделать этот звонок, и его нет в офисе на неделю.
Итак, в основном; есть ли способ повторно инициализировать статический класс после запуска веб-приложения? Мне просто нужно, чтобы он перезагрузил все свои свойства, как будто приложение было только что перестроено и запущено снова.
8 ответов
если приведенный выше код представляет ситуацию, в которой вы находитесь, вы не сможете повторно инициализировать код, если вы не сделаете что-то особенно хакерское с отражением (это не рекомендуется кстати).
Edit: о, подождите-я не знал, что это веб-приложение. Вы могли бы программно отскок приложения:
System.Web.HttpRuntime.UnloadAppDomain
ConstructorInfo constructor = typeof(Settings).GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,null, new Type[0], null);
constructor.Invoke(null, null);
вы можете использовать отражение:
var prop = typeof(Settings).GetField("setting1", BindingFlags.Static |
BindingFlags.Public);
prop.SetValue(null, "Bar");
string currentValue = Settings.setting1; //Bar
единственный вариант приходит мне на ум, который требует много работы:
- создать другой AppDomain
- загрузить сборку в другой домен
- используйте Remoting для получения данных
- Если настройки изменились, выгрузите AppDomain и выполните шаги с 1 по 3 снова
Я бы использовал отражение
var info = typeof(Settings)
.GetField("Settings",BindingFlags.Static|BindingFlags.Public);
info.SetValue(null, "setting4");
Хм, вы хотите найти способ взломать классе? даже если он существует с отражением и чем-то подобным, это не лучший способ решить это
быстрый обходной путь я могу предложить создать вам собственные не только статические свойства, инициализировать статические переменные и использовать их везде
но лучше будет использовать кэш или хранилища приложений вместо статических переменных
надеюсь, что это помогает
старый поток я знаю, но одна вещь, которую я сделал, это создать инициализации метод (public static void), который устанавливает все переменные (все они являются общедоступными статическими). В этом методе выполняются вызовы базы данных и устанавливаются переменные класса. Затем в коде, в любое время, когда вы хотите обновить переменные (т. е. в любое время, когда вы вызываете SaveChanges ()), вы можете вызвать Class.Initialize() и все готово.
Я использую это для кэширования общих списков информации поиска, которая может измениться, и мы должны держать это в синхронизации, когда база данных обновляется из приложения.
измените свои значения на свойства:
public static class Settings
{
public static setting1
{
get { return SettingmanagerClass.GetSetting("setting1"); }
}
public static setting2
{
get { return SettingmanagerClass.GetSetting("setting2");
}
public static setting3
{
get { return SettingmanagerClass.GetSetting("setting3");
}
}
кроме того, это не изменить сигнатуру кода.