如何将自定义对象的集合存储到user.config文件?

Dir*_*mar 33 c# collections configuration app-config

我想在user.config文件中存储一组自定义对象,并希望以编程方式从集合中添加和删除项目,然后将修改后的列表保存回配置文件.

我的项目具有以下简单形式:

class UserInfo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }        
}
Run Code Online (Sandbox Code Playgroud)

在我的app.config中,我已经创建了一个自定义部分:

<configuration>
  <configSections>
    <section name="userInfo" type="UserInfoConfigurationHandler, MyProgram"/>

  </configSections>
  <userInfo>
    <User firstName="John" lastName="Doe" email="john@example.com" />
    <User firstName="Jane" lastName="Doe" email="jane@example.com" />
  </userInfo>

</configuration>
Run Code Online (Sandbox Code Playgroud)

我也可以通过实现IConfigurationSectionHandler以下方式阅读设置:

class UserInfoConfigurationHandler : IConfigurationSectionHandler
{
    public UserInfoConfigurationHandler() { }

    public object Create(object parent, object configContext, System.Xml.XmlNode section)
    {
        List<UserInfo> items = new List<UserInfo>();
        System.Xml.XmlNodeList processesNodes = section.SelectNodes("User");

        foreach (XmlNode processNode in processesNodes)
        {
            UserInfo item = new UserInfo();
            item.FirstName = processNode.Attributes["firstName"].InnerText;
            item.LastName = processNode.Attributes["lastName"].InnerText;
            item.Email = processNode.Attributes["email"].InnerText;
            items.Add(item);
        }
        return items;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这篇文章之后做了所有这些.但是,使用这种方法,我只能将app.config中的设置List<UserInfo>集合,但我还需要编写修改后的列表.

我正在搜索文档但没有成功,现在我有点卡住了.我错过了什么?

Tim*_*ers 55

添加自定义配置的方法(如果您需要的不仅仅是简单类型)是使用ConfigurationSection,在您定义的模式中,您需要一个ConfigurationElementCollection(设置为没有名称的默认集合),其中包含ConfigurationElement,如下所示:

public class UserElement : ConfigurationElement
{
    [ConfigurationProperty( "firstName", IsRequired = true )]
    public string FirstName
    {
        get { return (string) base[ "firstName" ]; }
        set { base[ "firstName" ] = value;}
    }

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

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

    internal string Key
    {
        get { return string.Format( "{0}|{1}|{2}", FirstName, LastName, Email ); }
    }
}

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

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

    public void Add( UserElement element )
    {
        BaseAdd( element );
    }

    public void Clear()
    {
        BaseClear();
    }

    public int IndexOf( UserElement element )
    {
        return BaseIndexOf( element );
    }

    public void Remove( UserElement element )
    {
        if( BaseIndexOf( element ) >= 0 )
        {
            BaseRemove( element.Key );
        }
    }

    public void RemoveAt( int index )
    {
        BaseRemoveAt( index );
    }

    public UserElement this[ int index ]
    {
        get { return (UserElement) BaseGet( index ); }
        set
        {
            if( BaseGet( index ) != null )
            {
                BaseRemoveAt( index );
            }
            BaseAdd( index, value );
        }
    }
}

public class UserInfoSection : ConfigurationSection
{
    private static readonly ConfigurationProperty _propUserInfo = new ConfigurationProperty(
            null,
            typeof(UserElementCollection),
            null,
            ConfigurationPropertyOptions.IsDefaultCollection
    );

    private static ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection();

    static UserInfoSection()
    {
        _properties.Add( _propUserInfo );
    }

    [ConfigurationProperty( "", Options = ConfigurationPropertyOptions.IsDefaultCollection )]
    public UserElementCollection Users
    {
        get { return (UserElementCollection) base[ _propUserInfo ]; }
    }
}
Run Code Online (Sandbox Code Playgroud)

我保持UserElement类的简单,虽然它确实应该按照这个优秀的CodeProject文章中描述的完全声明每个属性的模式.如您所见,它代表您提供的配置中的"用户"元素.

UserElementCollection类只支持具有多个"user"元素,如果要在运行时修改它,则可以添加/删除/清除集合中的项目.

最后有UserInfoSection,它只是统计它有一个默认的"user"元素集合.

接下来是App.config文件的示例:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup>
      <section
        name="userInfo"
        type="ConsoleApplication1.UserInfoSection, ConsoleApplication1"
        allowDefinition="Everywhere"
        allowExeDefinition="MachineToLocalUser"
      />
    </sectionGroup>
  </configSections>

  <userInfo>
    <user firstName="John" lastName="Doe" email="John.Doe@company.com" />
    <user firstName="Jane" lastName="Doe" email="Jane.Doe@company.com" />
  </userInfo>
</configuration>
Run Code Online (Sandbox Code Playgroud)

如您所见,在此示例中,我在App.config中包含了一些userInfo/user元素.我还添加了设置,说它们可以在机器/应用/用户/漫游用户级别定义.

接下来我们需要知道如何在运行时更新它们,以下代码显示了一个示例:

Configuration userConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );

var userInfoSection = userConfig.GetSection( "userInfo" ) as UserInfoSection;

var userElement = new UserElement();

userElement.FirstName = "Sample";
userElement.LastName = "User";
userElement.Email = "Sample.User@company.com";

userInfoSection.Users.Add( userElement );

userConfig.Save();
Run Code Online (Sandbox Code Playgroud)

如果需要,上面的代码将创建一个新的user.config文件,深埋在用户的"Local Settings\Application Data"文件夹中.

如果您希望将新用户添加到app.config文件,只需将OpenExeConfiguration()方法的参数更改为ConfigurationUserLevel.None.

正如您所看到的,它相当简单,尽管找到这些信息需要进行一些挖掘.


Dan*_*ana 7

我不会将这种数据存储在app.config中,至少不会以编程方式进行更新.从概念上讲,它是用于配置设置,而不是应用程序数据,所以您可能希望将用户名和密码信息存储在单独的XML文件中(假设您不能或不想使用数据库)?

话虽如此,我认为最好的办法是将app.config作为标准XML文件读取,解析它,添加所需的节点并将其写回.内置的ConfigurationManager API不提供回写新设置的方法(我想这给出了微软预期用途的提示).