2016-02-27 91 views
2

这不是一个新问题,但我一直在研究这两天,所有我能找到的答案都是过时的或无益的。我想要做的是将一个对象放入App.config中,然后在程序启动时加载它。 (字符串)名字,(字符串)姓氏和(int)年龄。我有一个基本的类称为“人”与三个自动属性:(字符串)名字,(字符串)姓和(int)年龄。这是我的App.config文件:如何从app.config中读取对象?

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup> 
    <configSections> 
    <sectionGroup name="People"> 
     <section 
     name="Person" 
     type="Person.Person" 
     /> 
    </sectionGroup> 
    </configSections> 
    <People> 
    <Person> 
     <Person type="Person.Person, Person"> 
     <FirstName>Jimmy</FirstName> 
     <LastName>Dean</LastName> 
     <Age>2</Age> 
     </Person> 
    </Person> 
    </People> 
</configuration> 

这里是我的程序:

using System; 
using System.Configuration; 

namespace AppConfigTest 
{ 
    class AppConfigTester 
    { 
     public static void Main(string[] args) 
     { 
      var guy = (Person.Person) ConfigurationManager.GetSection("People/Person"); 
      Console.WriteLine(guy.FirstName); 
      Console.WriteLine(guy.LastName); 
      Console.WriteLine(guy.Age); 
     } 
    } 
} 

在其与ConfigurationErrorsException崩溃的时刻。任何帮助将非常感激。当App.config应该让这样的事情变得更简单时,我觉得这太难了。

+1

你在哪里定义自定义配置部分? https://msdn.microsoft.com/en-us/library/2tw134k3.aspx – David

+0

@David这是我错过了什么?我之前有一个,基于弃用的ConfigurationSettings,最终取消了它。在这一点上我很困惑。我会尽力做一个新的。 – randomraccoon

回答

4

给定一个人POCO类:

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
} 

首先,你需要ŧ Ø创建一个继承System.Configuration.ConfigurationElement像这样一类:

public class PersonElement : ConfigurationElement 
{ 
    public string InnerText { get; private set; } 

    protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey) 
    { 
     InnerText = reader.ReadElementContentAsString(); 
    } 
} 

这是必要的,所以你可以有配置元素,如<FirstName>Jimmy</FirstName>与内部文本。

接下来,你需要一个类继承System.Configuration.ConfigurationSection这样的:

public class PersonSection : ConfigurationSection 
{ 
    [ConfigurationProperty("FirstName")] 
    public PersonElement FirstName 
    { 
     get { return this["FirstName"] as PersonElement; } 
     set { this["FirstName"] = value; } 
    } 

    [ConfigurationProperty("LastName")] 
    public PersonElement LastName 
    { 
     get { return this["LastName"] as PersonElement; } 
     set { this["LastName"] = value; } 
    } 

    [ConfigurationProperty("Age")] 
    public PersonElement Age 
    { 
     get { return this["Age"] as PersonElement; } 
     set { this["Age"] = value; } 
    } 

    public Person CreatePersonFromConfig() 
    { 
     return new Person() 
     { 
      FirstName = this.FirstName.InnerText, 
      LastName = this.LastName.InnerText, 
      Age = Convert.ToInt32(this.Age.InnerText) 
     }; 
    } 
} 

你的app.config应该是这样的:

<configuration> 
    <configSections> 
     <sectionGroup name="People"> 
      <section name="Person" type="Example.PersonSection, Example" /> 
     </sectionGroup> 
    </configSections> 
    <People> 
     <Person> 
      <FirstName>Jimmy</FirstName> 
      <LastName>Dean</LastName> 
      <Age>2</Age> 
     </Person> 
    </People> 
</configuration> 

最后地方在你的代码做到这一点:

PersonSection config = (PersonSection)ConfigurationManager.GetSection("People/Person"); 
Person guy = config.CreatePersonFromConfig(); 
+2

哇,谢谢!我不知道我需要那个PersonElement类。这种学习曲线对我来说非常陡峭,所以我非常感谢帮助。 – randomraccoon

1

有几个与你的执行问题,它们是:

  1. <configSections>元素必须是第一个元素在你的App.config文件
  2. 配置节处理程序(即在上述类型type属性的section元素)必须从ConfigurationSection继承。
  3. 完全合格的,你指的是

<configSections>元素的类型必须是第一个元素在你的App.config文件

正被抛出的ConfigurationErrorsException包含以下细节:

只有一个< configSections>元素允许每个配置文件,如果存在必须是根的第一个孩子<配置>元素。

这就是说你必须将<configSections>元素移动到文件的顶部。我想这是这样的,处理配置文件的代码可以在之前的每个区段加载相应的处理程序它读取配置文件的每个部分。

配置节处理程序(即在section元素的type属性描述的类型),必须从ConfigurationSection

不幸的是,配置系统的工作方式继承意味着你不能只删除一个POCO请注意为您配线。有一个教程creating a custom configuration section on MSDN

完全合格的,你指的是

我不知道,这其实是造成你的问题的类型,但它不会伤害要精确,以避免它造成的一个问题。以下内容:

<section name="Person" type="Person.Person" /> 

可能含糊不清。假设你的项目编译名为“MyProjectThatContainsPerson”一个DLL/EXE,你应该考虑将其更改为:

<section name="Person" type="Person.Person, MyProjectThatContainsPerson" /> 

这清楚的配置系统不仅什么类型的名称是(Person.Person),但还应该尝试从(MyProjectThatContainsPerson)加载它的组件。

一个例子定制部分使用内置节处理

如果你想补充一点,有一个自定义名称的构成部分(例如,“MySection”),但在其他方面的表现一样appSettings,你可以有:

<configSections> 
    <section name="MySection" 
      type="System.Configuration.NameValueSectionHandler, system, 
        Version=1.0.3300.0, Culture=neutral, 
        PublicKeyToken=b77a5c561934e089, Custom=null" /> 
</configSections> 
<MySection> 
    <add key="MySetting" value="MyValue" /> 
</MySection>