Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以从外部文件初始化ConfigurationSection?_C#_.net_Config - Fatal编程技术网

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。第二,在循环包含链的情况下,这可能会导致无限循环。您可以为以前包含的文件创建一个
    列表
    ,然后在将其添加到队列之前检查该列表中是否已经存在该包含


    希望这对别人有帮助

    我今天在工作中遇到了这个问题。谢谢你的解决方案!