【问题标题】:How to add a field in my quartz configuration dynamically?如何在我的石英配置中动态添加字段?
【发布时间】:2018-01-29 23:25:31
【问题描述】:

我的 web.config 中有一个石英配置部分,我想向它添加一个键值字段。 (我知道我可以去 web.config 并手动添加它,但这违背了目的)

我试过用这种方式

var config = (NameValueCollection)WebConfigurationManager.GetSection("quartz");
config.Add("quartz.dataSource.quartzDS.connectionString", "data source =..");

但它失败了,因为集合是只读的,不能修改。任何提示如何做到这一点?

编辑:我最终将配置复制到 nameValueCollection,然后将其复制到另一个(对于只读属性)添加我想要的键值并将其传递给我需要的函数。

var oldConfig = (NameValueCollection)WebConfigurationManager.GetSection("quartz");
var config = Test(oldConfig);
var connectionString = unitOfWork.GetConnectionStringByTenantIdentifier(tenantId);
config.Add("quartz.dataSource.quartzDS.connectionString", connectionString);
await unitOfWork.GetService<SchedulerService>().StartScheduler(config, tenantId);

这样,我将按照我想要的方式为每个租户进行自定义配置。抱歉,如果我的问题不清楚。

【问题讨论】:

    标签: c# asp.net-web-api web-config quartz-scheduler


    【解决方案1】:

    您实际上可以通过两种方式做到这一点。 一种方法是在标准 AppSettings 部分设置您的动态连接字符串,然后使用一组新的 XML 属性创建一个新的 Quartz 调度程序(Quartz.NET 发行版中提供了一个示例,所以我会缩短这个)

    var properties = new NameValueCollection
        {
            ["quartz.scheduler.instanceName"] = "XmlConfiguredInstance",
            ["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz", 
            ... etc.
        };
    ISchedulerFactory sf = new StdSchedulerFactory(properties);
    IScheduler sched = await sf.GetScheduler();
    

    然后您可以将非常量字符串保存在 AppSettings 中并在那里获取它。

    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        config.AppSettings.Settings.Add("quartz.dataSource.quartzDS.connectionString", connstring);
        config.Save(ConfigurationSaveMode.Modified);
    ConfigurationManager.RefreshSection("appSettings");
    

    或者您可以将整个设置文件作为 XML 读取,如前所述,但是您必须确保在初始化默认 Quartz 调度程序之前完成所有编辑,因为它的属性变为只读,并且您可以更改它们无论如何都必须创建一个新的 ISchedulerFactory,这有点超出目的。

    var xmlDoc = new XmlDocument();
    xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    xmlDoc.SelectSingleNode("//quartz/add[@key='quartz.dataSource.quartzDS.connectionString']").Attributes["value"].Value = "...";
    xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    ConfigurationManager.RefreshSection("quartz");
    

    但我建议您不要在运行时编辑您的主配置文件,而是使用 ISchedulerFactory XmlConfiguredInstance,同时以您喜欢的任何格式将 connstring 保存到 UAC 兼容的位置(防止Modifying app.config at runtime throws exception发生)

    如果你想使用配置文件,你可以使用this tutorial from Yi Zeng进一步阅读

    【讨论】:

      【解决方案2】:

      您可以尝试使用 XmlDocument 类进入较低级别。 确保您应用的用户对配置文件具有写入权限

      public static void WriteKey(String configFileName, String key, String value)
          {
      
              XmlDocument doc = new XmlDocument();
              doc.Load(configFileName);
      
              XmlNode node = doc.SelectSingleNode("//quartz");
              if (node == null)
              {
                  throw new InvalidOperationException("quartz section not found in config file.");
              }
              try
              {
                  XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key));
                  if ((elem != null))
                  {
                      elem.SetAttribute("value", value);
                  }
                  else
                  {
                      elem = doc.CreateElement("add");
                      elem.SetAttribute("key", key);
                      elem.SetAttribute("value", value);
                      node.AppendChild(elem);
                  }
                  doc.Save(configFileName);
              }
              catch
              {
                  throw new InvalidOperationException("Error writing config file");
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-07
        • 1970-01-01
        相关资源
        最近更新 更多