.net - 如何在自定义 configSection 中指定集合

标签 .net configuration configuration-files

我想要一个 xml 配置文件,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
    <section name="plugins" type="MyApp.PluginsConfiguration, MyApp"/>
</configSections>

<plugins>
    <use assembly="MyApp.Plugin1.dll" />
    <use assembly="MyApp.Plugin2.dll" />
</plugins>
</configuration>

我到底如何安排代码中的 PluginsConfigurations、UsePluginCollection 和 UsePlugin 类之间的相互作用?

我找到了this tutorial在线,但它会在插件内部引入一个围绕 use 集合的元素,我不需要这个。

This是我到目前为止所拥有的,但不太正确

最佳答案

如果MyApp.PluginsConfiguration是一个ConfigurationSection,那么您可以定义一个继承自ConfigurationElementCollection的新类,并使新类成为MyApp.PluginsConfiguration的ConfigurationProperty

检查this article有关这些类型的一些深入信息。我也blogged about具有嵌套属性,但不是专门针对集合的。

编辑:这里有一些代码。 web.config 中给出了这一点:

<configSections>
    <section name="plugins"
             type="WebApplication1.PluginsConfiguration, WebApplication1"/>
</configSections>
<plugins>
    <use assembly="MyApp.Plugin1.dll"/>
    <use assembly="MyApp.Plugin2.dll"/>
</plugins>

这里是实现这一点的类。请注意,可能需要处理 NullReferenceException。

namespace WebApplication1
{
    public class PluginsConfiguration : ConfigurationSection
    {
        private static ConfigurationPropertyCollection properties;
        private static ConfigurationProperty propPlugins;

        static PluginsConfiguration()
        {
            propPlugins = new ConfigurationProperty(null, typeof(PluginsElementCollection),
                                                          null,
                                                          ConfigurationPropertyOptions.IsDefaultCollection);
            properties = new ConfigurationPropertyCollection { propPlugins };
        }

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                return properties;
            }
        }

        public PluginsElementCollection Plugins
        {
            get
            {
                return this[propPlugins] as PluginsElementCollection;
            }
        }
    }

    public class PluginsElementCollection : ConfigurationElementCollection
    {
        public PluginsElementCollection()
        {
            properties = new ConfigurationPropertyCollection();
        }

        private static ConfigurationPropertyCollection properties;

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                return properties;
            }
        }

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

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

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

        protected override object GetElementKey(ConfigurationElement element)
        {
            var elm = element as PluginsElement;
            if (elm == null) throw new ArgumentNullException();
            return elm.AssemblyName;
        }
    }

    public class PluginsElement : ConfigurationElement
    {
        private static ConfigurationPropertyCollection properties;
        private static ConfigurationProperty propAssembly;

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                return properties;
            }
        }

        public PluginsElement()
        {
            propAssembly = new ConfigurationProperty("assembly", typeof(string),
                                                          null,
                                                          ConfigurationPropertyOptions.IsKey);
            properties = new ConfigurationPropertyCollection { propAssembly };
        }

        public PluginsElement(string assemblyName)
            : this()
        {
            AssemblyName = assemblyName;
        }

        public string AssemblyName
        {
            get
            {
                return this[propAssembly] as string;
            }
            set
            {
                this[propAssembly] = value;
            }
        }
    }
}

要访问它,此代码片段应该有所帮助:

        var cfg = WebConfigurationManager.GetWebApplicationSection("plugins") as PluginsConfiguration;
        var sb = new StringBuilder();
        foreach(PluginsElement elem in cfg.Plugins)
        {
            sb.AppendFormat("{0}<br/>", elem.AssemblyName);
        }
        testLabel.Text = sb.ToString();

基本上我们有一个处理插件元素的 ConfigurationSection。在此,我们指定一个 ConfigurationElementCollection 属性并将其声明为默认集合(理论上,您可以在一个根节点下拥有多个不同的集合)。

PluginsElementCollection 实现 ConfigurationElementCollection。 ElementName 必须是标签的名称,在我们的例子中是“use”。此外,GetElementKey 需要被重写,并且应该返回一个在条目中唯一的属性。

PluginsElement 然后实现单次使用标记。我们只定义一个属性:AssemblyName,它映射到程序集属性。

我并不声称完全理解所有这些(特别是 ConfigurationElementCollection 及其各种 BaseAdd、BaseGet 等属性。此处并未真正探讨),但我可以声称这是有效的:)

此外,它不使用任何属性。我讨厌属性 - 幸运的是,所有这些属性都可以转换为正确的代码。您可以使用其中之一(或两者)。

关于.net - 如何在自定义 configSection 中指定集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2002715/

相关文章:

c# - WCF 调用是否处理传输和接收的对象?

c# - 使用 TempData 在 Controller 操作之间传递细节是不好的做法吗?

c# - Windows 回调,当事件窗口改变时

java - 如何从 Eclipse 设置 java.library.path

configuration - 如何更改 Visual Studio Code 快速修复语言?

java - 有没有一种编程方式可以找出 Spring bean 是如何创建的?

c# - DataGridViewCheckBoxColumn : FormatException on boolean-column

c++ - VS2010中不同的解决方案配置

mongodb - 如何在 mongodb 配置文件中设置授权?

c# - 在 C# 中存储应用程序设置