How to add a field in my quartz configuration dynamically?

让人想犯罪 __ 提交于 2019-12-11 08:53:44

问题


I have a quartz configuration section in my web.config, and I want to add a key value field to it. (I know I can just go to the web.config and add it manually but that defeats the purpose)

I tried using this way

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

but it failed because collection is read only and can't be modified. Any tip to how to do this?

Edit: I ended up copying the config to a nameValueCollection and then copying it to another one (for the readonly properties) add the key values I want and passing it to the function I needed.

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

this way I will have the custom configuration for every tenant the way I want it. Sorry if my question wasn't clear.


回答1:


You can actually do this in two ways. One way is to set your dynamic connection string in the standard AppSettings section and then create a new Quartz Scheduler with a new set of XML properties (an example is provided in Quartz.NET distribution, so I will cut this short)

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

Then you can save your non-const string in the AppSettings and get it form there.

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

Or you can read your whole settings file as XML, as previously answered, BUT you have to make sure that any edits are done before you initialize the default Quartz Scheduler, as it's properties become read-only, and to change them you will have to create a new ISchedulerFactory anyway, which kinda beats the purpose.

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

But I advise you not to edit your main config file at runtime at all, and instead use an ISchedulerFactory XmlConfiguredInstance while getting and saving the connstring into a UAC-compatible location in any format you like (to prevent Modifying app.config at runtime throws exception from happening)

Still if you want to use the config file you can use this tutorial from Yi Zeng for further reading




回答2:


You can try using XmlDocument classes to go to a lower level. Make sure the user of your app has write permissions to the config file

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


来源:https://stackoverflow.com/questions/48497228/how-to-add-a-field-in-my-quartz-configuration-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!