【问题标题】:C# - Re-initialize static class?C# - 重新初始化静态类?
【发布时间】:2012-05-04 05:04:16
【问题描述】:

我正在处理的 Web 应用程序中有一个包含客户端设置的类。对于某些背景,我不拥有这个类,并且改变它不是一种选择。我们最近添加了一些逻辑来将设置存储在数据库中,我的任务是创建一个页面来编辑它们,这很公平。

这是我的问题;这些设置保存在一个静态类中,它们本身就是静态的只读属性。例如

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”;它可以很好地保存到数据库中,但现在我需要将它作为新值反映在 Web 应用程序中。由于它是静态类的静态只读属性,因此只有在应用首次连接时才会调用它,并且无法手动设置。

重申一下,我不拥有原始类,因此“仅使属性可写”不是(当前)有效的选项。通常我会和我的老板讨论这个问题,他会做出判断,并可能允许我修改另一个班级,但我无法做出那个决定,而且他这周都不在办公室。

基本上是这样;一旦 Web 应用程序开始运行,有没有办法重新初始化静态类?我只需要让它重新加载它的所有属性,就好像应用刚刚重建并重新启动一样。

【问题讨论】:

  • 您可以通过反射更改它或回收该过程。 Here is a thread关于如何进行反思:
  • 附注:您知道所有设置(例如来自 web.config)都被缓存了吗?
  • 是否可以重新启动 IIS? Start or Stop an Application Pool (IIS 7)
  • 最好的办法是反射或反弹 IIS AppDomain 来装箱静态数据。下面详细介绍这两者。当你的老板回来时,获得批准以制定适当的解决方案并摆脱static readonly 成员。小心,我已经看到并且仍然看到很多比我的编程生涯更早的“临时黑客”。
  • 真的,任何建议都会比让它们可写更难看,我知道你说这“不是(当前)有效的选项”,但它会是最干净的......跨度>

标签: c# class static


【解决方案1】:
  ConstructorInfo constructor = typeof(Settings).GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,null, new Type[0], null);
  constructor.Invoke(null, null);

【讨论】:

  • 谢谢。我用 OPs 类进行了测试,以确保比发布:)
  • 我厌倦了这个,我确实工作了,但是出于某种奇怪的原因,尽管调试器显示了更新的值,但 Web 应用程序继续在页面中加载原始值。很奇怪,虽然我这次没用,但我会坚持那个,很好,即使现在纯粹是学术原因(对我来说)。
  • 那是邪恶的。以为我将不得不重构我的缓存类,但这是黑魔法,谢谢,
  • 谢谢。这是邪恶的,但它有效。倒影很可怕
【解决方案2】:

你可以使用反射:

var prop = typeof(Settings).GetField("setting1", BindingFlags.Static | 
                                                 BindingFlags.Public);
prop.SetValue(null, "Bar");
string currentValue = Settings.setting1; //Bar

【讨论】:

    【解决方案3】:

    如果上面的代码代表了你所处的情况,你将无法重新初始化代码,除非你用反射做一些特别的黑客行为(顺便说一下,不推荐这样做)。

    编辑:哦等等 - 我没有意识到这是一个网络应用程序。你可以通过编程方式bounce the application:

    System.Web.HttpRuntime.UnloadAppDomain
    

    【讨论】:

    • 这可能很危险,但如果系统中有其他用户并且会话因弹跳而丢失。
    • 我实际上只是针对我在原始帖子中列出的场景进行了测试,它确实有效;完全没有会话丢失,只是重新加载了设置。完美的。我已经对其进行了几次测试,以确保我不仅对感知到的成功感到兴奋,而且从我所见,这是纯粹的胜利,谢谢!
    • @ddietle - 我很高兴这对你有用,但我对你的会话没有被破坏感到困惑。您是否将会话存储在进程之外(例如在 SQL Server 中)?
    • 这正是他们处理它的方式(SQL 状态服务器)。我想这是我的运气。
    • 更新:我(幸运地)能够获得处理这是“正确”方式的许可,我将使用 get 和 set 将属性从只读属性更改为标准属性。 松了一口气
    【解决方案4】:

    我想到的唯一选择是需要大量工作:

    1. 创建另一个 AppDomain
    2. 在其他域中加载程序集
    3. 使用 Remoting 获取数据
    4. 如果设置更改,请卸载 AppDomain 并再次执行步骤 1 到 3

    【讨论】:

      【解决方案5】:

      我会使用反射

      var info = typeof(Settings)
      .GetField("Settings",BindingFlags.Static|BindingFlags.Public);
      info.SetValue(null, "setting4");
      

      【讨论】:

        【解决方案6】:
        public static class Settings
        {
           public static name = "";
        
           static Settings()
           {
            ReInitialize();
           }
        
           public static void ReInitialize()
           {
              name = "My name is re-initialized";
           }
        }
        
        
        Settings.name = "My name has changed";
        // Console.WriteLine(Settings.name);
        Settings.ReInitialize(); //name is "My name is re-initialized"
        // Console.WriteLine(Settings.name);
        

        【讨论】:

          【解决方案7】:

          嗯,你想找到破解课程的方法吗?即使它存在反射之类的东西,也不是解决这个问题的好方法

          快速解决方法我可以建议您创建自己的非只读静态属性,使用该静态变量进行初始化并在任何地方使用它们

          但最好使用缓存或应用程序存储而不是静态变量

          希望对你有帮助

          【讨论】:

          • 使用会话不适合存储范围为整个应用程序的数据。此外,OP 表示他不拥有违规代码。
          • 已编辑,确定@RQDQ,应用程序或缓存会更好
          【解决方案8】:

          我知道旧线程,但我所做的一件事是创建一个 Initialize 方法(public static void)来设置所有变量(它们都是 public static)。在该方法中,进行数据库调用并设置类的变量。然后在代码中,只要你想刷新变量(即任何时候调用 SaveChanges()),你就可以调用 Class.Initialize() 就完成了。

          我使用它来缓存可以更改的常见查找信息列表,并且我们需要在从应用程序更新数据库时保持同步。

          【讨论】:

            【解决方案9】:

            将您的值更改为属性:

            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");
             }
            }
            

            此外,这不会更改代码的签名。

            【讨论】:

            • 他说,“(目前)不是一个有效的选择。”我编码的方式保留了readonly 字段(如果这是客户或规范要求)。必须有所改变才能提供这一点。
            • 澄清一下,我没有投反对票。无论哪种方式,确切单词的语义。如果 OP 可以编辑代码,那么这个问题就不会存在了。
            • 除了很好的用例之外,这个答案今天帮助我解决了一个不相关的问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-05-18
            • 2018-08-13
            • 1970-01-01
            • 2020-04-14
            • 2011-08-26
            • 2021-12-31
            • 1970-01-01
            相关资源
            最近更新 更多