응용 프로그램 설정에 int [] 배열을 저장하는 방법


93

저는 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을 검색했지만이를 수행하는 방법에 대한 적절한 설명을 찾을 수 없습니다.

내가 찾은 드문 예제를 기반으로 한 내 직감은 배열 또는 목록을 래핑하는 직렬화 가능한 클래스를 만들어야한다는 것입니다. 그러면 설정 디자이너에서 해당 유형을 사용할 수 있습니다. 그러나 정확히 어떻게 해야할지 모르겠습니다.

답변:


137

또 다른 솔루션이 있습니다. 설정 파일을 약간 수동으로 편집해야하지만 나중에 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 설정 이 있습니다.


5
대박. Visual Studio의 편집기를 사용하여 설정에 입력하려면 다음과 같이 붙여 넣어야합니다. 이것은 문자열 배열 용입니다. <? xml version = "1.0"encoding = "utf-16"?> <ArrayOfString XMLNS : XSI = " w3.org/2001/XMLSchema-instance "의 xmlns : XSD = " w3.org/2001/XMLSchema "> <문자열> 문자열 1 </ 문자열> <문자열> 문자열 2 </ 문자열> </ ArrayOfString>
Karsten

9
+1 .. 왜 이것이 받아 들여지지 않았는지 이해하지 못합니다 .. 추가 코드가 필요하지 않으며 (기존 xml의 한 줄만 수정하십시오) 형식 안전성과 완전한 대 디자이너 지원을 얻습니다!
Chris

1
Chris, 고마워요 :) 문제는 훨씬 늦게 내 답변을 추가 한 것입니다 (약 1 년 후 실제로 :)). 그래도 경험 공유 :)
Jen-Ari

6
궁금한 사람을 위해 구성 파일 XML 구문 int[]은 다음과 같습니다 (예쁜 인쇄 제외).<setting name="SomeTestSetting" serializeAs="String"><value><ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><int>1</int><int>2</int><int>3</int></ArrayOfInt></value></setting>
aaaantoine

1
동의합니다. 이것이 더 나은 답변이므로 마크를 변경했습니다.
sidewinderguy

40

저장하려면 :

string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());

다시 만들려면 :

int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();

편집 : Abel 제안!


좋아, 이것은 데이터를 문자열로 수동으로 직렬화하는 것처럼 보이며 그 반대의 경우도 마찬가지입니다. 나는 이것이 효과가 있다고 생각한다. 나는 단지 데이터를 문자열 설정으로 저장할 수있다. 나는 이와 같은 일을 할 생각을했지만 더 "깨끗한"또는 "표준"또는 더 많은 .NET '을 찾고있었습니다. 더 나은 것이 없다면 나는 이것을 명심할 것입니다. 감사.
sidewinderguy

안녕하세요, 저는 McKay의 거리로 갈 것입니다! (구성 섹션 / 섹션 그룹)
Mike Gleason jr Couturier

간단하기 때문에 이것으로 갈 것입니다. 모든 아이디어에 감사드립니다. 앞으로도 도움이 될 것입니다.
sidewinderguy

2
참고 : System.Linq위의 트릭이 작동하려면 사용 / 가져 오기에 추가해야합니다.
Sean Hanley

11

이 결과를 얻을 수있는 또 다른 방법은 사용이 훨씬 깨끗하지만 더 많은 코드가 필요합니다. 사용자 지정 형식 및 형식 변환기를 구현하면 다음 코드가 가능합니다.

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 클래스를 선택하기 만하면됩니다.

다시 말하지만 이것은 훨씬 더 많은 코드입니다. 그러나 단순한 배열보다 훨씬 복잡한 유형의 데이터에 적용 할 수 있습니다.


감사합니다. 기회가되면 시험해 볼게요.
sidewinderguy

3

설정을 System.Collections.ArrayList로 지정하고 다음을 수행합니다.

Settings.Default.IntArray = new ArrayList(new int[] { 1, 2 });

int[] array = (int[])Settings.Default.IntArray.ToArray(typeof(int));

2

간단한 해결책은 속성에서 설정의 기본값을 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;
        }
    }
}

일종의 해키 느낌이 들지만 생성자가 호출되기 전에 속성이 마지막 (또는 기본) 설정으로 초기화되기 때문에 깨끗하고 원하는대로 작동합니다.


2
응용 프로그램 설정 파일의 디자이너가 코드를 자동 생성하므로 이와 같은 변경 사항은 실수로도 디자이너를 사용할 때마다 덮어 쓰게됩니다.
Carl G

1

사용 System.Object.

예:

byte[] arBytes = new byte[] { 10, 20, 30 };
Properties.Settings.Default.KeyObject = arBytes;

추출물:

arBytes = (byte[])Properties.Settings.Default.KeyObject;

1
System.Object를 사용해 보았지만 설정이 세션간에 유지되지 않았습니다. (네, 그것은 내가 IDE를 사용하여 디버깅하지 않은, 릴리스 빌드는 독립형 그것을 부르기 위하여 당신이 원한다 무엇 이건, 설치했다)
엠마누엘 Vintilă

0

설정을 직렬화하는 것이 옳다고 생각합니다. 샘플은이 질문에 대한 내 대답을 참조하십시오.

두 앱간에 구성을 공유하는 기술?

다음과 같은 배열 인 속성이 있습니다.

/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
[XmlAttribute]
public int [] Numbers { get; set; }

0

문자열에서 int 배열을 변환하는 일부 함수를 만드십시오. 그러나 각각 사이에 ""(공백)과 같은 문자를 넣으십시오.

따라서 배열이 {1,34,546,56}이면 문자열은 "1 34 645 56"이됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.