[c#] 응용 프로그램 설정에 int [] 배열을 저장하는 방법
저는 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[]
) 또는 정수 목록 (List< int >
. 그러나 이것을 수행하는 방법을 알 수 없습니다. 문서, stackoverflow 및 google을 검색했지만이를 수행하는 방법에 대한 적절한 설명을 찾을 수 없습니다.
내가 찾은 드문 예제를 기반으로 한 내 직감은 배열 또는 목록을 래핑하는 직렬화 가능한 클래스를 만들어야한다는 것입니다. 그러면 설정 디자이너에서 해당 유형을 사용할 수 있습니다. 그러나 정확히 어떻게 해야할지 모르겠습니다.
답변
또 다른 솔루션이 있습니다. 설정 파일을 약간 수동으로 편집해야하지만 나중에 VS 환경과 코드에서 잘 작동합니다. 추가 기능이나 래퍼가 필요하지 않습니다.
문제는 VS int[]
가 설정 파일에서 기본적으로 유형 을 직렬화 할 수 있다는 것입니다 . 기본적으로 선택할 수는 없습니다. 따라서 원하는 이름 (예 : SomeTestSetting)으로 설정을 만들고 모든 유형 (예 :string
: 기본적으로)으로 만듭니다. 변경 사항을 저장하십시오.
이제 프로젝트 폴더로 이동하여 텍스트 편집기 (예 : 메모장)로 “Properties \ Settings.settings”파일을 열거 나 솔루션 탐색기에서 “-> 속성-> Settings.settings를 마우스 오른쪽 단추로 클릭하여 VS에서 열 수 있습니다. “에서”연결 프로그램 … “을 선택한 다음”XML 편집기 “또는”소스 코드 (텍스트) 편집기 “를 선택합니다. 열린 xml 설정에서 설정을 찾습니다 (다음과 같이 표시됨).
<Setting Name="SomeTestSetting" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
“Type”매개 변수를에서 System.String
로 변경하십시오 System.Int32[]
. 이제이 섹션은 다음과 같습니다.
<Setting Name="SomeTestSetting" Type="System.Int32[]" Scope="User">
<Value Profile="(Default)" />
</Setting>
이제 변경 사항을 저장하고 프로젝트 설정을 다시 엽니 다-voilà! – System.Int32[]
코드에서뿐만 아니라 VS 설정 디자이너 (값도)를 통해 액세스하고 편집 할 수있는 유형이 있는 SomeTestSetting 설정 이 있습니다.
답변
저장하려면 :
string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());
다시 만들려면 :
int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();
편집 : Abel 제안!
답변
이 결과를 얻을 수있는 또 다른 방법은 사용이 훨씬 깨끗하지만 더 많은 코드가 필요합니다. 사용자 지정 형식 및 형식 변환기를 구현하면 다음 코드가 가능합니다.
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 클래스에 몇 가지 편리한 메서드를 제공하면 List에 안전하게 할당 할 수 있으며 전체 클래스는 다음과 같습니다.
[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인지 확인한 다음 실제 기본값으로 설정합니다. 따라서 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; }