代码之家  ›  专栏  ›  技术社区  ›  Dirk Vollmar

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

  •  33
  • Dirk Vollmar  · 技术社区  · 16 年前

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

    我的项目采用以下简单形式:

    class UserInfo
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }        
    }
    

    在我的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>
    

    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;
        }
    }
    

    article . 然而,使用这种方法,我只能 List<UserInfo> 收集,但我也需要 修改后的列表返回。

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

    5 回复  |  直到 16 年前
        1
  •  55
  •   Timothy Walters    12 年前

    添加自定义配置(如果您需要的不仅仅是简单类型)的方法是使用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 ]; }
        }
    }
    

    我保持了UserElement类的简单性,尽管它实际上应该遵循中描述的完全声明每个属性的模式 this excellent CodeProject article . 正如您所见,它表示您提供的配置中的“用户”元素。

    最后是UserInfoSection,它只是统计它有一个默认的“用户”元素集合。

    接下来是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>
    

    如您所见,在这个示例中,我在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();
    

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

        2
  •  7
  •   Dana    16 年前

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

        3
  •  1
  •   Michael Piendl    16 年前

    使用 刚出现的 来自.Net Framework的System.Configuration API 2. (程序集:系统配置)

    你可以在网站上找到很多非常好的样品和说明 http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx

    还有一个代码示例,介绍如何修改和保存值。


    编辑:

    如果存在任何更改,则仅保存修改后的值

    Configuration.Save() 
    

    保存指定级别的更改(如果存在任何更改)

    Configuration.Save(ConfigurationSaveMode) 
    

    保存指定级别的更改,如果第二个参数为true,则强制执行保存

    Configuration.Save(ConfigurationSaveMode, bool)
    

    ConfigurationSaveMode枚举具有以下值:

    • -保存所有配置属性,无论它们是否已更改
    • -保存已修改的特性,即使当前值与原始值相同
    • -仅保存已修改且值与原始值不同的特性
        4
  •  0
  •   Rince Thomas Janny    12 年前
     private void frmLocalFileTransfer_Load(object sender, EventArgs e)
        {
            try
            {
                dt.Columns.Add("Provider");
                dt.Columns.Add("DestinationPath");
                string[] folders = null;
                dt.Columns.Add("SourcePath");
    
                for (int i = 1; i < System.Configuration.ConfigurationManager.ConnectionStrings.Count; i++)
                {
                    string key = System.Configuration.ConfigurationManager.ConnectionStrings[i].Name;
                    string constr = System.Configuration.ConfigurationManager.ConnectionStrings[i].ConnectionString;
                    DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
                    folders = constr.Split('\\');
                    string newstr = (folders[folders.Length - 2]);
                    if (!newstr.Contains("BackUp"))
                    {
                        DataRow row = dt.NewRow();
                        row[dt.Columns[0].ToString()] = key;
                        row[dt.Columns[1].ToString()] = constr;
                        row[dt.Columns[2].ToString()] = constr;
                        dt.Rows.InsertAt(row, i - 1);
                    }
                }
    
                foreach (DataColumn dc in dt.Columns)
                {
                    DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
                    column.DataPropertyName = dc.ColumnName;
                    column.HeaderText = dc.ColumnName;
                    column.Name = dc.ColumnName;
                    column.SortMode = DataGridViewColumnSortMode.Automatic;
                    column.ValueType = dc.DataType;
                    GVCheckbox();
    
                    gevsearch.Columns.Add(column);
                }
                if (gevsearch.ColumnCount == 4)
                {
                    DataGridViewButtonColumn btnColoumn = new DataGridViewButtonColumn();
                    btnColoumn.Width = 150;
                    btnColoumn.HeaderText = "Change SourcePath";
                    btnColoumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                    gevsearch.Columns.Insert(4, btnColoumn);
    
    
                }
                 gevsearch.DataSource = dt;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    
    private void btnAddProvider_Click(object sender, EventArgs e)
        {
            try
            {
                System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
                path = "D:\\Pandurang\\Jitendra\\LocalFileTransfer\\LocalFileTransfer
                xDoc.Load(path);
                System.Xml.XmlElement element = xDoc.CreateElement("add");
                element.SetAttribute("name", txtProviderName.Text.Trim());
                element.SetAttribute("connectionString", txtNewPath.Text.Trim());
                System.Xml.XmlElement elementBackup = xDoc.CreateElement("add");
                elementBackup.SetAttribute("name", BackUpName);
                elementBackup.SetAttribute("connectionString", txtBackupPath.Text.Trim());
                System.Xml.XmlNode node= xDoc.ChildNodes[1].ChildNodes[0];
                node.AppendChild(element);
                node.AppendChild(elementBackup);
                xDoc.Save(path);
              }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    
        5
  •  -1
  •   0100110010101    16 年前

    您应该创建一个类,如:

    public class MySettings : ConfigurationSection 
    {
        public MySettings Settings = (MySettings)WebConfigurationManager.GetSection("MySettings");
    
        [ConfigurationProperty("MyConfigSetting1")]
        public string DefaultConnectionStringName
        {
            get { return (string)base["MyConfigSetting1"]; }
            set { base["MyConfigSetting1"] = value; }
        }
    }
    

    <section name="MySettings" type="MyNamespace.MySettings"/>
    <MySettings MyConfigSetting1="myValue">
    

    就是这样) 如果您不想使用attibutes,而想使用properties,只需创建从ConfigurationElement派生的类,并将其包含到从ConfigurationSettings定义的类中即可。