C# 是否可以从外部文件初始化ConfigurationSection?
我的应用程序中有一个自定义配置属性。它看起来像这样:C# 是否可以从外部文件初始化ConfigurationSection?,c#,.net,config,C#,.net,Config,我的应用程序中有一个自定义配置属性。它看起来像这样: public class OverrideConfiguration : ConfigurationSection { [ConfigurationProperty(PROP_ADMIN_CONNSTR)] public StringConfigurationElement AdminConnectionString { get { return base[PROP_ADMIN_CONNSTR] as
public class OverrideConfiguration : ConfigurationSection
{
[ConfigurationProperty(PROP_ADMIN_CONNSTR)]
public StringConfigurationElement AdminConnectionString
{
get { return base[PROP_ADMIN_CONNSTR] as StringConfigurationElement; }
set { base[PROP_ADMIN_CONNSTR] = value; }
}
// .. Various other properties, but you get the idea
}
<ServiceOverrides file="Overrides.local.config" />
但是,我希望允许将.config文件指向外部文件源。大概是这样的:
public class OverrideConfiguration : ConfigurationSection
{
[ConfigurationProperty(PROP_ADMIN_CONNSTR)]
public StringConfigurationElement AdminConnectionString
{
get { return base[PROP_ADMIN_CONNSTR] as StringConfigurationElement; }
set { base[PROP_ADMIN_CONNSTR] = value; }
}
// .. Various other properties, but you get the idea
}
<ServiceOverrides file="Overrides.local.config" />
现在,内置的configSource
属性接近我所需要的,但它有两个主要问题
。\Overrides.local.config
配置元素几乎相同。但是,该属性似乎是实现的appSettings
,而不是基本ConfigurationSection
类的一部分
我的问题:
是否可以覆盖
ConfigurationSection
中基本上从不同位置读取XML数据的内容?我不想改变我的类的任何其他方面,也不想做我自己的XML反序列化或任何事情。我只想检查一个文件是否存在,如果存在,请加载该文件中的XML内容,否则加载默认的XML内容。好的,我有一个可行的解决方案。我不确定这是否是最好的方法,但它似乎确实能按我所希望的方式工作
private readonly Queue<String> externalSources = new Queue<String>();
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
var externalFile = reader.GetAttribute("File");
if(!String.IsNullOrWhiteSpace(externalFile))
{
externalSources.Enqueue(externalFile);
}
base.DeserializeElement(reader, serializeCollectionKey);
}
protected override void PostDeserialize()
{
base.PostDeserialize();
// Override data with local stuff
if (externalSources.Count == 0) return;
string file = externalSources.Dequeue();
if (System.IO.File.Exists(file))
{
var reader = XmlReader.Create(file);
base.DeserializeSection(reader);
}
}
private readonly Queue externalSources=new Queue();
受保护的重写void反序列化元素(XmlReader、bool serializeCollectionKey)
{
var externalFile=reader.GetAttribute(“文件”);
如果(!String.IsNullOrWhiteSpace(externalFile))
{
externalSources.Enqueue(externalFile);
}
反序列化元素(读取器,serializeCollectionKey);
}
受保护的重写void PostDeserialize()
{
base.PostDeserialize();
//用本地内容覆盖数据
if(externalSources.Count==0)返回;
字符串文件=externalSources.Dequeue();
if(System.IO.File.Exists(File))
{
var reader=XmlReader.Create(文件);
反序列化部分(读卡器);
}
}
首先,我捕获了反序列化元素
事件,它发生在我们读取
元素时。我们检查它是否有File
属性,如果有,我们将其添加到要加载的外部源队列中
接下来,我们捕获PostDeserialize
事件,在解析所有本地XML之后调用该事件。如果队列中有外部源,我们将其出列,检查它是否确实存在,然后使用该文件的内容创建一个XmlReader
。现在,我们只需再次调用反序列化部分
,然后传入新的读取器。ConfigurationSection
类足够智能,可以将任何新数据覆盖或附加到现有配置中。最后我得到的是两个配置文件的聚合,其中包含文件在出现重复时获胜
现在,排队是怎么回事?好吧,似乎每次调用反序列化部分
,它都会再次调用后反序列化
。因此,如果我们简单地捕获后反序列化
,检查文件
属性,然后再次调用反序列化部分
,我们将进入一个无限循环。我们可以使用一个标志来记住我们是否已经加载了外部文件,但是队列还有一个额外的好处,即允许include文件加载更多的include文件(这不是我想做的,但是您可以)
提示:这可能会很好地工作,并且很容易理解,但是如果您在生产代码中使用它,则有一些地方可以改进。首先,externalSources
实际上不需要是队列,因为这些调用实际上不是递归的。您可能只需使用字符串
,并在处理完该文件后将其设置为null。第二,在循环包含链的情况下,这可能会导致无限循环。您可以为以前包含的文件创建一个列表
,然后在将其添加到队列之前检查该列表中是否已经存在该包含
希望这对别人有帮助 我今天在工作中遇到了这个问题。谢谢你的解决方案!