私は、C#express 2008を使用して単純なWindows Formsアプリケーションを作成しています。私は経験豊富なC++開発者ですが、C#と.NETにはまったく新しいです。
現在、設定デザイナーと次のようなコードを使用して、簡単なアプリケーション設定の一部を保存しています。
// Store setting
Properties.Settings.Default.TargetLocation = txtLocation.Text;
...
// Restore setting
txtLocation.Text = Properties.Settings.Default.TargetLocation;
ここで、intの配列(int[]
)、または場合によってはintのリスト(List< int >
)、設定として。ただし、これを行う方法がわかりません。ドキュメント、stackoverflow、およびgoogleを検索しましたが、これを行う方法の適切な説明が見つかりません。
私が見つけたまばらな例に基づいた私の考えは、配列またはリストをラップするシリアライズ可能なクラスを作成する必要があり、設定デザイナーでそのタイプを使用できるようになるということです。ただし、これを行う方法は正確にはわかりません。
別の解決策もあります-設定ファイルを少し手作業で編集する必要がありますが、その後はVS環境とコードで問題なく動作します。また、追加の関数やラッパーは必要ありません。
VSは、設定ファイルでint[]
タイプをデフォルトでシリアル化できることです-デフォルトで選択することはできません。そのため、希望する名前(SomeTestSettingなど)で設定を作成し、任意のタイプ(デフォルトではstring
など)にします。変更を保存します。
プロジェクトフォルダーに移動し、テキストエディター(たとえば、メモ帳)で "Properties\Settings.settings"ファイルを開きます。または、ソリューションエクスプローラーで "-> Properties-> Settings.settingsを右クリックして、VSで開くことができます。 、[開く...]を選択し、[XMLエディター]または[ソースコード(テキスト)エディター]を選択します。開いたxml設定で設定を見つけます(次のようになります)。
<Setting Name="SomeTestSetting" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
「タイプ」パラメータをSystem.String
からSystem.Int32[]
に変更します。このセクションは次のようになります。
<Setting Name="SomeTestSetting" Type="System.Int32[]" Scope="User">
<Value Profile="(Default)" />
</Setting>
ここで、変更を保存し、プロジェクト設定を再度開きます-voilà! -タイプSystem.Int32[]
を使用したSomeTestSettingの設定があり、VS Settings Designer(値も)およびコード内でアクセスおよび編集できます。
保存する:
string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());
再作成するには:
int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();
編集:アベルの提案!
この結果を達成するためのもう1つの方法があります。これは、使用方法はずっときれいですが、より多くのコードが必要です。カスタムタイプとタイプコンバーターを実装するには、次のコードが可能です。
List<int> array = Settings.Default.Testing;
array.Add(new Random().Next(10000));
Settings.Default.Testing = array;
Settings.Default.Save();
これを実現するには、文字列との変換を許可する型コンバーターを備えた型が必要です。これを行うには、TypeConverterAttributeで型を修飾します。
[TypeConverter(typeof(MyNumberArrayConverter))]
public class MyNumberArray ...
次に、この型コンバーターをTypeConverterの派生として実装します。
class MyNumberArrayConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
{ return (type == typeof(string)); }
public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
{ return (type == typeof(string)); }
public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
{
MyNumberArray arr = value as MyNumberArray;
StringBuilder sb = new StringBuilder();
foreach (int i in arr)
sb.Append(i).Append(',');
return sb.ToString(0, Math.Max(0, sb.Length - 1));
}
public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
{
List<int> arr = new List<int>();
if (data != null)
{
foreach (string txt in data.ToString().Split(','))
arr.Add(int.Parse(txt));
}
return new MyNumberArray(arr);
}
}
MyNumberArrayクラスでいくつかの便利なメソッドを提供することにより、リストとの間で安全に割り当てることができ、完全なクラスは次のようになります。
[TypeConverter(typeof(MyNumberArrayConverter))]
public class MyNumberArray : IEnumerable<int>
{
List<int> _values;
public MyNumberArray() { _values = new List<int>(); }
public MyNumberArray(IEnumerable<int> values) { _values = new List<int>(values); }
public static implicit operator List<int>(MyNumberArray arr)
{ return new List<int>(arr._values); }
public static implicit operator MyNumberArray(List<int> values)
{ return new MyNumberArray(values); }
public IEnumerator<int> GetEnumerator()
{ return _values.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator()
{ return ((IEnumerable)_values).GetEnumerator(); }
}
最後に、設定でこれを使用するには、上記のクラスをアセンブリに追加してコンパイルします。 Settings.settingsエディターで、「参照」オプションをクリックしてMyNumberArrayクラスを選択するだけです。
繰り返しますが、これはより多くのコードです。ただし、単純な配列よりもはるかに複雑なタイプのデータに適用できます。
System.Collections.ArrayListとして設定を指定してから、次の操作を行います。
Settings.Default.IntArray = new ArrayList(new int[] { 1, 2 });
int[] array = (int[])Settings.Default.IntArray.ToArray(typeof(int));
簡単な解決策は、プロパティで設定のデフォルト値をnullに設定することですが、コンストラクターでプロパティがnullであるかどうかを確認し、nullの場合は実際のデフォルト値に設定します。したがって、intの配列が必要な場合:
public class ApplicationSettings : ApplicationSettingsBase
{
public ApplicationSettings()
{
if( this.SomeIntArray == null )
this.SomeIntArray = new int[] {1,2,3,4,5,6};
}
[UserScopedSetting()]
[DefaultSettingValue("")]
public int[] SomeIntArray
{
get
{
return (int[])this["SomeIntArray"];
}
set
{
this["SomeIntArray"] = (int[])value;
}
}
}
ちょっとハック感がありますが、コンストラクターが呼び出される前にプロパティが最後の(またはデフォルトの)設定に初期化されるため、きれいで希望どおりに動作します。
中古 System.Object
。
例:
byte[] arBytes = new byte[] { 10, 20, 30 };
Properties.Settings.Default.KeyObject = arBytes;
エキス:
arBytes = (byte[])Properties.Settings.Default.KeyObject;
設定をシリアル化するのは正しいと思います。サンプルについては、この質問に対する私の答えをご覧ください。
次のような配列のプロパティがあります。
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
[XmlAttribute]
public int [] Numbers { get; set; }
文字列のint配列を変換する関数をいくつか作成しますが、それぞれの間に ""(スペース)のような文字を入れます。
したがって、配列が{1,34,546,56}の場合、文字列は「1 34 645 56」になります