Я создаю простое приложение Windows Forms с помощью C # express 2008. Я опытный разработчик на C ++, но в значительной степени новичок в C # и .NET.
В настоящее время я сохраняю некоторые из моих простых настроек приложения с помощью конструктора настроек и такого кода:
// Store setting
Properties.Settings.Default.TargetLocation = txtLocation.Text;
...
// Restore setting
txtLocation.Text = Properties.Settings.Default.TargetLocation;
Теперь я хотел бы сохранить либо массив ints ( int[]
), либо, возможно, List of ints ( List< int >
) в качестве настройки. Однако я не могу понять, как это сделать. Я искал документацию, stackoverflow и google, и я не могу найти достойного объяснения, как это сделать.
Моя догадка, основанная на редких примерах, которые я нашел, заключается в том, что мне нужно создать сериализуемый класс, который обертывает мой массив или список, а затем я смогу использовать этот тип в конструкторе настроек. Однако я не совсем уверен, как это сделать.
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>
хранить:
string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());
воссоздать:
int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();
Изменить: предложение Авеля!
источник
System.Linq
Чтобы описанный выше трюк сработал, вам нужно будет добавить к своим usings / import.Есть еще один способ достичь этого результата, который намного чище в использовании, но требует большего количества кода. Я использую собственный преобразователь типов и типов, возможен следующий код:
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, и если да, то установите его фактическое значение по умолчанию. Итак, если вам нужен массив 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»
источник