C# 如何在 ConfigurationElementCollection 中拥有自定义属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8829414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 04:40:49  来源:igfitidea点击:

how to have custom attribute in ConfigurationElementCollection?

c#.net-4.0configuration-files

提问by jojo

for configuration as following

配置如下

<MyCollection default="one">
  <entry name="one" ... other attrubutes />
  ... other entries
</MyCollection>

when implement a MyCollection, what should i do for the "default" attribute?

实现 MyCollection 时,我应该为“默认”属性做什么?

采纳答案by Simon Mourier

Let's suppose you have this .config file:

假设你有这个 .config 文件:

<configuration>
    <configSections>
        <section name="mySection" type="ConsoleApplication1.MySection, ConsoleApplication1" /> // update type  & assembly names accordingly
    </configSections>

    <mySection>
        <MyCollection default="one">
            <entry name="one" />
            <entry name="two" />
        </MyCollection>
    </mySection>
</configuration>

Then, with this code:

然后,使用此代码:

public class MySection : ConfigurationSection
{
    [ConfigurationProperty("MyCollection", Options = ConfigurationPropertyOptions.IsRequired)]
    public MyCollection MyCollection
    {
        get
        {
            return (MyCollection)this["MyCollection"];
        }
    }
}

[ConfigurationCollection(typeof(EntryElement), AddItemName = "entry", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class MyCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new EntryElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        return ((EntryElement)element).Name;
    }

    [ConfigurationProperty("default", IsRequired = false)]
    public string Default
    {
        get
        {
            return (string)base["default"];
        }
    }
}

public class EntryElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
    public string Name
    {
        get
        {
            return (string)base["name"];
        }
    }
}

you can read the configuration with the 'default' attribute, like this:

您可以使用“默认”属性读取配置,如下所示:

    MySection section = (MySection)ConfigurationManager.GetSection("mySection");
    Console.WriteLine(section.MyCollection.Default);

This will output "one"

这将输出“一”

回答by Fabio

I don't know if it's possible to have a default value in a ConfigurationElementCollection. (it doesn't seen to have any property for default value).

我不知道是否可以在 ConfigurationElementCollection 中设置默认值。(它没有看到任何默认值的属性)。

I guess you have to implement this by yourself. Look at the example below.

我想你必须自己实现这个。看看下面的例子。

public class Repository : ConfigurationElement
{
    [ConfigurationProperty("key", IsRequired = true)]
    public string Key
    {
        get { return (string)this["key"]; }
    }

    [ConfigurationProperty("value", IsRequired = true)]
    public string Value
    {
        get { return (string)this["value"]; }
    }
}

public class RepositoryCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new Repository();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return (element as Repository).Key;
    }

    public Repository this[int index]
    {
        get { return base.BaseGet(index) as Repository; }
    }

    public new Repository this[string key]
    {
        get { return base.BaseGet(key) as Repository; }
    }

}

public class MyConfig : ConfigurationSection
{
    [ConfigurationProperty("currentRepository", IsRequired = true)]
    private string InternalCurrentRepository
    {
        get { return (string)this["currentRepository"]; }
    }

    [ConfigurationProperty("repositories", IsRequired = true)]
    private RepositoryCollection InternalRepositories
    {
        get { return this["repositories"] as RepositoryCollection; }
    }
}

Here's the XML config:

这是 XML 配置:

  <myConfig currentRepository="SQL2008">
    <repositories>
      <add key="SQL2008" value="abc"/>
      <add key="Oracle" value="xyz"/>
    </repositories>
  </myConfig>

And then, at your code, you access the default item using the following:

然后,在您的代码中,您可以使用以下命令访问默认项目:

MyConfig conf = (MyConfig)ConfigurationManager.GetSection("myConfig");
string myValue = conf.Repositories[conf.CurrentRepository].Value;

Of course, the MyConfig class can hide the details of accessing the Repositories and CurrentRepository properties. You can have a property called DefaultRepository (of type Repository) in MyConfig class to return this.

当然,MyConfig 类可以隐藏访问 Repositories 和 CurrentRepository 属性的详细信息。您可以在 MyConfig 类中有一个名为 DefaultRepository(Repository 类型)的属性来返回它。

回答by GaTechThomas

If you want to genericize it, this should help:

如果您想对其进行泛化,这应该会有所帮助:

using System.Configuration;

namespace Abcd
{
  // Generic implementation of ConfigurationElementCollection.
  [ConfigurationCollection(typeof(ConfigurationElement))]
  public class ConfigurationElementCollection<T> : ConfigurationElementCollection
                                         where T : ConfigurationElement, IConfigurationElement, new()
  {
    protected override ConfigurationElement CreateNewElement()
    {
      return new T();
    }

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

    public T this[int index]
    {
      get { return (T)BaseGet(index); }
    }

    public T GetElement(object key)
    {
      return (T)BaseGet(key);
    }
  }
}

Here's the interface referenced above:

这是上面引用的接口:

namespace Abcd
{
  public interface IConfigurationElement
  {
    object GetElementKey();
  }
}

回答by clattaclism

This may be a bit late but may be helpful to others.

这可能有点晚,但可能对其他人有帮助。

It is possible but with some modification.

这是可能的,但需要进行一些修改。

  • ConfigurationElementCollection inherits ConfigurationElement as such "this[string]" is available in ConfigurationElement.

  • Usually when ConfigurationElementCollection is inherited and implemented in another class, the "this[string]" is hidden with "new this[string]".

  • One way to get around it is to create another implementation of this[] such as "this[string, string]"

  • ConfigurationElementCollection 继承了 ConfigurationElement,因为“this[string]”在 ConfigurationElement 中可用。

  • 通常在另一个类中继承并实现ConfigurationElementCollection时,“this[string]”会被“new this[string]”隐藏起来。

  • 绕过它的一种方法是创建 this[] 的另一个实现,例如“this[string, string]”

See example below.

请参阅下面的示例。

public class CustomCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new CustomElement();
    }

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

    public CustomElement this[int index]
    {
        get { return (CustomElement)base.BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
                BaseRemoveAt(index);

            BaseAdd(index, value);
        }
    }

    // ConfigurationElement this[string] now becomes hidden in child class
    public new CustomElement this[string name]
    {
        get { return (CustomElement)BaseGet(name); }
    }

    // ConfigurationElement this[string] is now exposed
    // however, a value must be entered in second argument for property to be access
    // otherwise "this[string]" will be called and a CustomElement returned instead
    public object this[string name, string str = null]
    {
        get { return base[name]; }
        set { base[name] = value; }
    }
}