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