web-dev-qa-db-ja.com

カスタムオブジェクトのコレクションをuser.configファイルに保存するにはどうすればよいですか?

カスタムオブジェクトのコレクションを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="[email protected]" />
    <User firstName="Jane" lastName="Doe" email="[email protected]" />
  </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;
    }
}

私はこれに続いてこれをすべて行いました 記事 。ただし、このアプローチを使用すると、app.configからList<UserInfo>コレクションに設定を読み取ることしかできませんが、必要なこともあります変更されたリストをwriteに戻します。

私は成功せずにドキュメントを検索していましたが、今はちょっと行き詰まっています。何が足りないのですか?

33
Dirk Vollmar

その種のデータをapp.configに保存することはありません。少なくとも、プログラムで更新することを意図している場合はそうではありません。概念的には、これは構成設定用であり、アプリケーションデータ用ではないため、ユーザー名とパスワードの情報を別のXMLファイルに保存したい場合があります(データベースを使用できない、または使用したくない場合)。

そうは言っても、最善の策は、app.configを標準のXMLファイルとして読み取り、解析し、必要なノードを追加して、書き戻すことだと思います。組み込みのConfigurationManagerAPIは、新しい設定を書き戻す方法を提供していません(これは、Microsoftの使用目的に関するヒントを提供すると思います)。

7
Dana

カスタム構成を追加する方法(単純な型以上のものが必要な場合)は、ConfigurationSectionを使用することです。定義したスキーマ内で、次のように、ConfigurationElementを含むConfigurationElementCollection(名前のないデフォルトのコレクションとして設定)が必要です。 :

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クラスは単純にしていますが、 この優れたCodeProjectの記事 で説明されているように、各プロパティを完全に宣言するパターンに従う必要があります。ご覧のとおり、これは指定した構成の「ユーザー」要素を表しています。

UserElementCollectionクラスは、実行時にコレクションを変更する場合にコレクションからアイテムを追加/削除/クリアする機能など、複数の「ユーザー」要素を持つことをサポートするだけです。

最後に、「user」要素のデフォルトのコレクションがあることを単に統計する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="[email protected]" />
    <user firstName="Jane" lastName="Doe" email="[email protected]" />
  </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 = "[email protected]";

userInfoSection.Users.Add( userElement );

userConfig.Save();

上記のコードは、必要に応じて新しいuser.configファイルを作成し、ユーザーの「ローカル設定\アプリケーションデータ」フォルダーの奥深くに埋め込みます。

代わりに、新しいユーザーをapp.configファイルに追加する場合は、OpenExeConfiguration()メソッドのパラメーターをConfigurationUserLevel.Noneに変更するだけです。

ご覧のとおり、この情報を見つけるには少し掘り下げる必要がありましたが、それはかなり簡単です。

55
Timothy Walters

.Net Framework2。newSystem.ConfigurationAPIを使用します(Assembly:System.Configuration) IConfigurationSectionHandlerは廃止されました。

非常に優れたサンプルと説明がたくさんあります http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx

値を変更および保存する方法についてのコードサンプルもあります。


編集:codeprojectのドキュメントの関連部分

変更が存在する場合、変更された値のみを保存します

Configuration.Save() 

変更が存在する場合は、指定したレベルの変更を保存します

Configuration.Save(ConfigurationSaveMode) 

指定されたレベルの変更を保存し、2番目のパラメーターがtrueの場合に強制的に保存します

Configuration.Save(ConfigurationSaveMode, bool)

ConfigurationSaveMode列挙には次の値があります。

  • Full-変更されているかどうかに関係なく、すべての構成プロパティを保存します
  • Modified-現在の値が元の値と同じであっても、変更されたプロパティを保存します
  • Minimal-変更され、元の値とは異なる値を持つプロパティのみを保存します
1
Michael Piendl
 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());
        }
    }
0