【问题标题】:Custom Configuration for app.config - collections of sections?app.config 的自定义配置 - 部分的集合?
【发布时间】:2011-11-04 10:29:09
【问题描述】:

我的头在剧烈地跳动!我以前做过这件事,但没有那么“深入”或复杂,我尝试了不同的方法来实现这一点,但都失败了。

所以,这是我想要的 app.config 中的自定义 XML:

<Profiles> <!--Collection-->
<Profile Name="Live">
   <Components>
    <Component Name="Portal" Type="Web" />
    <Component Name="Comms" Type="Web" />
    <Component Name="Scheduler" Type="WindowsService" ServiceName="LiveScheduler" />
  </Components>
  <Databases>
    <Database Name="Main" Connection="Data Source=.\SQL2008" />
    <Database Name="Staging" Connection="Data Source=SomeSite.co.uk" />
  </Databases>
</Profile>
<Profile Name="Test">
   <Components>
    <Component Name="Portal" Type="Web" />
    <Component Name="Comms" Type="Web" />
    <Component Name="Scheduler" Type="WindowsService" ServiceName="TestScheduler" />
  </Components>
  <Databases>
    <Database Name="Main" Connection="Data Source=.\SQL2008" />
    <Database Name="Staging" Connection="Data Source=Internal" />
  </Databases>
</Profile>
</Profiles>

所以一个 Profile 的集合,每个 Profile 都有一个子元素的集合(Components 是一个集合,然后 Component 是一个元素)

但是,我目前拥有多个配置文件之外的所有内容。我确实看到了问题,但不确定如何“修复”它。

代码:

public class Profile : ConfigurationSection
{
    [ConfigurationProperty("Name", IsRequired=true)]
    public string Name
    {
        get
        {
            return base["Name"] as string;
        }
            set
            {
                base["Name"] = value;
            }
        }

        [ConfigurationProperty("Components")]
        public ComponentCollection Components
        {
            get { return ((ComponentCollection)(base["Components"])); }
        }

        [ConfigurationProperty("Databases")]
        public DatabaseCollection Databases
        {
            get
            {
                return ((DatabaseCollection)(base["Databases"]));
            }
        }
    }

    [ConfigurationCollection(typeof(Component), AddItemName="Component")] 
    public class ComponentCollection : ConfigurationElementCollection
    {        
        protected override ConfigurationElement CreateNewElement()
        {
            return new Component();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Component)(element)).Name;
        }

        public Component this[int idx]
        {
            get
            {
                return base.BaseGet(idx) as Component;
            }
            set
            {
                if (base.BaseGet(idx) != null)
                {
                    base.BaseRemoveAt(idx);
                }
                this.BaseAdd(idx, value);
            }
        }

        public Component this[string key]
        {
            get
            {
                return base.BaseGet(key) as Component;
            }
            set
            {
                if (base.BaseGet(key) != null)
                {
                    base.BaseRemove(key);
                }
                this.BaseAdd(this.Count, value);
            }
        }
    }

    public class Component : ConfigurationElement
    {
        [ConfigurationProperty("Type", IsRequired = true)]
        public string Type
        {
            get
            {
                return this["Type"] as string;
            }
            set
            {
                this["Type"] = value;
            }
        }

        [ConfigurationProperty("Name", IsRequired = true, IsKey = true)]
        public string Name
        {
            get
            {
                return this["Name"] as string;
            }
            set
            {
                this["Name"] = value;
            }
        }

        [ConfigurationProperty("ServiceName", IsRequired = false)]
        public string ServiceName
        {
            get
            {
                return this["ServiceName"] as string;
            }
            set
            {
                this["ServiceName"] = value;
            }
        }
    }

    [ConfigurationCollection(typeof(Database), AddItemName = "Database")] 
    public class DatabaseCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new Database();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Database)(element)).Name;
        }


        public Database this[int idx]
        {
            get
            {
                return base.BaseGet(idx) as Database;
            }
            set
            {
                if (base.BaseGet(idx) != null)
                {
                    base.BaseRemoveAt(idx);
                }
                this.BaseAdd(idx, value);
            }
        }

        public Database this[string key]
        {
            get
            {
                return base.BaseGet(key) as Database;
            }
            set
            {
                if (base.BaseGet(key) != null)
                {
                    base.BaseRemove(key);;
                }

                this.BaseAdd(this.Count, value);
            }
        }
    }

    public class Database : ConfigurationElement
    {
        [ConfigurationProperty("Name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get
            {
                return this["Name"] as string;
            }
            set
            {
                this["Name"] = value;
            }
        }

        [ConfigurationProperty("Connection", IsKey = false, IsRequired = true)]
        public string Connection
        {
            get
            {
                return this["Connection"] as string;
            }
            set
            {
                this["Connection"] = value;
            }
        }
    }

【问题讨论】:

  • 您似乎正在尝试为不同的环境使用不同的配置文件,您为什么不看看本周发布的 VS 的 Slow Cheetah 扩展。几乎可以满足您的需求:sadev.co.za/content/…
  • 关于代码问题的任何信息?

标签: c# .net app-config


【解决方案1】:

除了需要一个额外的级别之外,您的实现是正确的。将 Profile 从 ConfigurationSection 更改为 ConfigurationElement,然后创建一个包含 Profile 项集合的 ConfigurationSection Profiles。

这是一个很好的自动化测试案例,调试配置部分不费吹灰之力。

【讨论】:

  • 谢谢大家到目前为止的回复。 Cheetah 扩展看起来很有趣。
  • 哎呀.. 输入太快了。 ssamuel - 我相信我之前尝试过你的方法,但除了抛出异常说它需要实现 IConfigurationSectionHandler 之外没有其他地方。我会看看我能不能再做一次。但我想知道将对象序列化/反序列化为 XML 并老实说使用它是否更快:-/
  • 呃,你用的是什么版本的固件? IConfigurationSectionHandler 在 2.0 之后被弃用。如果你还在寻找,try this。 Serialize-to-XML 更快、更直观。写入配置更漂亮。维护的难度取决于您想留在哪里,系统管理员或开发人员。
【解决方案2】:

您需要将配置部分上移一级。

public class Profiles : ConfigurationSection
{
    [ConfigurationProperty("Profile")]
    public ProfileCollection Profile
    {
        get
        {
            return this["profile"] as ProfileCollection;
        }
    }
}    

这是我创建的一个部分。您应该可以通过以下方式让您的工作:

public class ImportConfiguration : ConfigurationSection
{
    [ConfigurationProperty("importMap")]
    public ImportMapElementCollection ImportMap
    {
        get
        {
            return this["importMap"] as ImportMapElementCollection;
        }
    }
}

public class ImportColumnMapElement : ConfigurationElement
{
    [ConfigurationProperty("localName", IsRequired = true, IsKey = true)]
    public string LocalName
    {
        get
        {
            return this["localName"] as string;
        }
        set
        {
            this["localName"] = value;
        }
    }

    [ConfigurationProperty("sourceName", IsRequired = true)]
    public string SourceName
    {
        get
        {
            return this["sourceName"] as string;
        }
        set
        {
            this["sourceName"] = value;
        }
    }
}

public class ImportMapElementCollection : ConfigurationElementCollection
{
    public ImportColumnMapElement this[object key]
    {
        get
        {
            return base.BaseGet(key) as ImportColumnMapElement;
        }
    }

    public override ConfigurationElementCollectionType CollectionType
    {
        get
        {
            return ConfigurationElementCollectionType.BasicMap;
        }
    }

    protected override string ElementName
    {
        get
        {
            return "columnMap";
        }
    }

    protected override bool IsElementName(string elementName)
    {
        bool isName = false;
        if (!String.IsNullOrEmpty(elementName))
            isName = elementName.Equals("columnMap");
        return isName;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new ImportColumnMapElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ImportColumnMapElement)element).LocalName;
    }
}

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2012-10-04
    • 2015-07-05
    • 2011-05-25
    • 2011-09-16
    • 2010-10-20
    • 1970-01-01
    • 2012-09-07
    • 2013-05-19
    相关资源
    最近更新 更多