如何在我的石英配置中动态添加一个字段?
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 进一步阅读
我的 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 进一步阅读