ส่วน app.config ที่กำหนดเองพร้อมรายการองค์ประกอบ "เพิ่ม" แบบง่ายๆ


88

ฉันจะสร้างส่วน app.config ที่กำหนดเองซึ่งเป็นเพียงรายการaddองค์ประกอบง่ายๆได้อย่างไร

ฉันพบตัวอย่างบางส่วน (เช่นวิธีสร้างส่วนกำหนดค่าที่กำหนดเองใน app.config? ) สำหรับส่วนที่กำหนดเองที่มีลักษณะดังนี้:

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

แต่ฉันจะหลีกเลี่ยงองค์ประกอบคอลเลกชันพิเศษ ("บริษัท ") ได้อย่างไรเพื่อให้ดูเหมือนกับส่วนappSettingsและconnectionStringsส่วนต่างๆ กล่าวอีกนัยหนึ่งฉันต้องการ:

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

คำตอบ:


114

ตัวอย่างเต็มพร้อมรหัสตามไฟล์กำหนดค่า 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

3
ควรระบุด้วยว่า <add is required. การสร้างแท็ก <ที่กำหนดเองของคุณใช้ไม่ได้กับคำตอบนี้
สตีฟเป็น

8
AFAIK - รหัสนี้ "config [" Tata Motors "]" จะไม่รวบรวม b / c ตัวทำดัชนีของ config ได้รับการป้องกันภายใน คุณจะต้องหาวิธีแจกแจงรายการในคอลเลกชันด้วยตัวคุณเอง
CedricB

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 คุณพูดถูก มันไม่ได้ตอบอย่างเคร่งครัด หากคุณต้องใช้ชื่อแอตทริบิวต์ / รหัสแทนคีย์ / ค่าโซลูชันของฉันคุณจะต้องใช้ส่วนที่กำหนดเองอย่างแท้จริง อย่างไรก็ตามฉันถือว่าคุณเป็นผู้ควบคุมไฟล์ config และมีสิ่งที่ดีกว่าการสร้างคลาสแบบกำหนดเอง
JJS

4
เรียบง่ายและสะอาดมาก! ไม่จำเป็นต้องใช้ bloatware ส่วน / องค์ประกอบที่กำหนดเองเพิ่มเติม
Ondřej

2
คุณยังสามารถอัปเดตเป็นเวอร์ชัน = 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 การเข้าถึงองค์ประกอบต่างๆจำเป็นต้องทำโดยการทำซ้ำผ่านคอลเลกชัน "อินสแตนซ์" กล่าวคือ.

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.