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

时间:2018-01-29 08:35:41

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

我的web.config中有一个石英配置部分,我想为它添加一个键值字段。 (我知道我可以直接进入web.config并手动添加它,但这样做会失败)

我尝试过这种方式

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

但它失败了,因为收集是只读的,无法修改。有关如何做到这一点的任何提示?

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

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

这样我将按照我想要的方式为每个租户提供自定义配置。对不起,如果我的问题不清楚。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

您实际上可以通过两种方式执行此操作。 一种方法是在标准的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兼容的位置(防止[{3}}发生)

如果您想使用配置文件,可以使用Modifying app.config at runtime throws exception进一步阅读