如何在我的石英配置中动态添加一个字段?

How to add a field in my quartz configuration dynamically?

我的 web.config 中有一个 quartz 配置部分,我想向其中添加一个键值字段。 (我知道我可以转到 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);

这样我就可以按照我想要的方式为每个租户进行自定义配置。对不起,如果我的问题不清楚。

您可以尝试使用 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");
        }
    }

您实际上可以通过两种方式做到这一点。 一种方法是在标准 AppSettings 部分中设置动态连接字符串,然后使用一组新的 XML 属性创建一个新的 Quartz Scheduler(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 Scheduler 之前完成所有编辑,因为它的属性变为只读,并且要更改它们,您无论如何都必须创建一个新的 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 进一步阅读