간단한 "추가"요소 목록이있는 사용자 지정 app.config 섹션


88

단순한 add요소 목록 인 사용자 지정 app.config 섹션을 만들려면 어떻게해야 합니까?

다음과 같은 사용자 지정 섹션에 대한 몇 가지 예 (예 : app.config에서 사용자 지정 구성 섹션을 만드는 방법? )를 찾았습니다.

<RegisterCompanies>
  <Companies>
    <Company name="Tata Motors" code="Tata"/>
    <Company name="Honda Motors" code="Honda"/>
  </Companies>
</RegisterCompanies>

그러나 추가 수집 요소 ( "Companies")를 피하여 appSettingsconnectionStrings섹션 과 동일하게 보이도록하려면 어떻게해야 합니까? 즉, 다음을 원합니다.

<registerCompanies>
  <add name="Tata Motors" code="Tata"/>
  <add name="Honda Motors" code="Honda"/>
</registerCompanies>

답변:


115

OP 구성 파일을 기반으로하는 코드가있는 전체 예제 :

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

다음은 축소 된 컬렉션이있는 사용자 지정 구성 섹션을 구현하는 샘플 코드입니다.

using System.Configuration;
namespace My {
public class MyConfigSection : ConfigurationSection {
    [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
    public MyConfigInstanceCollection Instances {
        get { return (MyConfigInstanceCollection)this[""]; }
        set { this[""] = value; }
    }
}
public class MyConfigInstanceCollection : ConfigurationElementCollection {
    protected override ConfigurationElement CreateNewElement() {
        return new MyConfigInstanceElement();
    }

    protected override object GetElementKey(ConfigurationElement element) {
        //set to whatever Element Property you want to use for a key
        return ((MyConfigInstanceElement)element).Name;
    }
}

public class MyConfigInstanceElement : ConfigurationElement {
    //Make sure to set IsKey=true for property exposed as the GetElementKey above
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name {
        get { return (string) base["name"]; }
        set { base["name"] = value; }
    }

    [ConfigurationProperty("code", IsRequired = true)]
    public string Code {
        get { return (string) base["code"]; }
        set { base["code"] = value; }
    } } }

다음은 코드에서 구성 정보에 액세스하는 방법의 예입니다.

var config = ConfigurationManager.GetSection("registerCompanies") 
                 as MyConfigSection;

Console.WriteLine(config["Tata Motors"].Code);
foreach (var e in config.Instances) { 
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
}

@Jay Walker 필요한 항목에 액세스하는 방법은 다음과 같습니다. 예 :-config.Instances [ "Tata Motors"]이 작업이 가능합니까?
Simon

2
종료 지점해야 <configSection>직후에해야 <configuration>일에 대한 태그!
Vedran Kopanja 2014

2
또한 <add가 필요함을 지적해야합니다. 당신 자신의 사용자 정의 <태그이 응답 작동하지 않습니다 만들기
스티브는 D

8
AFAIK-이 코드 "config ["Tata Motors "]"는 구성의 인덱서가 내부적으로 보호되고 b / c 컴파일되지 않습니다. 컬렉션의 항목을 직접 열거하는 방법을 찾아야합니다.
CedricB 2015

1
@JayWalker 모두 좋습니다. 섹션 유형에 대한 예제의 "My.MyConfiguration, My.Assembly"가 나를 던져줍니다. 나는 내가 시도한 것에 대해 "MyAssembly.MyConfiguration, MyAssembly"를 사용해야 만했다.
Glen

38

사용자 지정 구성 섹션이 필요하지 않습니다.

App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="YourAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </configSections>
    <!-- value attribute is optional. omit if you just want a list of 'keys' -->
    <YourAppSettings>
        <add key="one" value="1" />
        <add key="two" value="2"/>
        <add key="three" value="3"/>
        <add key="duplicate" value="aa"/>
        <add key="duplicate" value="bb"/>
    </YourAppSettings>
</configuration>

검색

// This casts to a NameValueCollection because the section is defined as a 
/// AppSettingsSection in the configSections.
NameValueCollection settingCollection = 
    (NameValueCollection)ConfigurationManager.GetSection("YourAppSettings");

var items = settingCollection.Count;
Debug.Assert(items == 4); // no duplicates... the last one wins.
Debug.Assert(settingCollection["duplicate"] == "bb");

// Just keys as per original question? done... use em.
string[] allKeys = settingCollection.AllKeys;

// maybe you did want key/value pairs. This is flexible to accommodate both.
foreach (string key in allKeys)
{
    Console.WriteLine(key + " : " + settingCollection[key]);
}

1
OP의 질문에 엄격하게 대답하는 것은 아니지만 유효한 해결책이며 훨씬 더 간단한 해결책이라고 생각합니다. 적어도 그것은 나를 도왔습니다!
styl0r

2
@ styl0r 당신이 맞아요. 엄격하게 대답 하지 않습니다 . 내 솔루션 키 / 값 대신 속성 이름 / 코드를 사용해야하는 경우 진정한 사용자 지정 섹션을 사용해야합니다. 그러나 나는 당신이 구성 파일을 제어하고 있으며 사용자 정의 클래스를 만드는 것보다 더 좋은 일이 있다고 가정합니다.
JJS

4
매우 간단하고 깨끗합니다! 추가 사용자 지정 섹션 / 요소 블로 트웨어가 필요하지 않습니다.
Ondřej

2
원하는 경우 버전 번호를 변경하여 Version = 4.0.0.0으로 업데이트 할 수도 있습니다. 추가 간단한 목록이 필요한 경우 이것이 가장 좋은 대답입니다. "System.Configuration.ConnectionStringsSection"에 대해서도 동일한 작업을 수행 할 수 있지만 중복은 앱 설정과 약간 다르게 처리됩니다.
Sharpiro

@Sharpiro 어셈블리 버전에 문제가 있었습니까? 새 버전의 프레임 워크에서도 어셈블리 바인딩이 속도가 빠르다고 생각했습니다.
JJS

22

의 Jay Walker의 답변을 기반으로 , 이것은 인덱싱을 수행하는 기능을 추가하는 완전한 작업 예제입니다.

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

다음은 축소 된 컬렉션이있는 사용자 지정 구성 섹션을 구현하는 샘플 코드입니다.

using System.Configuration;
using System.Linq;
namespace My
{
   public class MyConfigSection : ConfigurationSection
   {
      [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
      public MyConfigInstanceCollection Instances
      {
         get { return (MyConfigInstanceCollection)this[""]; }
         set { this[""] = value; }
      }
   }
   public class MyConfigInstanceCollection : ConfigurationElementCollection
   {
      protected override ConfigurationElement CreateNewElement()
      {
         return new MyConfigInstanceElement();
      }

      protected override object GetElementKey(ConfigurationElement element)
      {
         //set to whatever Element Property you want to use for a key
         return ((MyConfigInstanceElement)element).Name;
      }

      public new MyConfigInstanceElement this[string elementName]
      {
         get
         {
            return this.OfType<MyConfigInstanceElement>().FirstOrDefault(item => item.Name == elementName);
         }
      }
   }

   public class MyConfigInstanceElement : ConfigurationElement
   {
      //Make sure to set IsKey=true for property exposed as the GetElementKey above
      [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
      public string Name
      {
         get { return (string)base["name"]; }
         set { base["name"] = value; }
      }

      [ConfigurationProperty("code", IsRequired = true)]
      public string Code
      {
         get { return (string)base["code"]; }
         set { base["code"] = value; }
      }
   }
}

다음은 코드에서 구성 정보에 액세스하는 방법의 예입니다.

MyConfigSection config = 
   ConfigurationManager.GetSection("registerCompanies") as MyConfigSection;

Console.WriteLine(config.Instances["Honda Motors"].Code);
foreach (MyConfigInstanceElement e in config.Instances)
{
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}

2
이것은 훌륭합니다. 이제 인스턴스를 업데이트, 추가 및 삭제하기위한 예제 코드 만 필요합니다.
Scott Hutchinson

1
솔루션에 감사드립니다! MS에서 만든 사람 ... 이건 정말 불필요하게 복잡합니다.
Switch386

8

Jay Walker의 답변에 따라 "Instances"컬렉션을 반복하여 요소에 액세스해야합니다. 즉.

var config = ConfigurationManager.GetSection("registerCompanies") 
                 as MyConfigSection;

foreach (MyConfigInstanceElement e in config.Instances) { 
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.