using System.Text; using ProjectCruiser.DrawningSamples; using ProjectCruiser.Exceptions; namespace ProjectCruiser.CollectionGenericObj; public class StorageCollection where T : DrawningBase // class { // Разделитель для записи ключа и значения элемента словаря private readonly string _separatorForKeyValue = "|"; // Разделитель для записей коллекции данных в файл private readonly string _separatorItems = ";"; // Ключевое слово, с которого должен начинаться файл private readonly string _collectionKey = "CollectionsStorage"; // Словарь (хранилище) с коллекциями < name, type (class) > readonly Dictionary> _storages; // Возвращение списка названий коллекций public List Keys => _storages.Keys.ToList(); public StorageCollection() { _storages = new Dictionary>(); } // Добавление коллекции в хранилище public void AddCollection(string name, CollectionType collType) { if (name == null || _storages.ContainsKey(name) || collType == CollectionType.None) { return; } ICollectionGenObj collection = CreateCollection(collType); _storages.Add(name, collection); } // Удаление коллекции ( по ключу-строке - её имени ) public void DelCollection(string name) { if (_storages.ContainsKey(name)) _storages.Remove(name); return; } // Доступ к коллекции ( по ключу-строке - её имени ) - индексатор [!!!] public ICollectionGenObj? this[string name] { get => _storages.ContainsKey(name) ? _storages[name] : null; } /// Сохранение информации по автомобилям в хранилище в файл /// Путь и имя файла /// true - сохранение прошло успешно, /// false - ошибка при сохранении данных public void SaveData(string filename) { if (_storages.Count == 0) throw new NullReferenceException(" > No existing collections to save"); if (File.Exists(filename)) { File.Delete(filename); } StringBuilder sb = new(); sb.Append(_collectionKey); // const foreach (KeyValuePair> pair in _storages) { sb.Append(Environment.NewLine); // не сохраняем пустые коллекции if (pair.Value.Count == 0) { continue; } sb.Append(pair.Key); sb.Append(_separatorForKeyValue); sb.Append(pair.Value.GetCollectionType); sb.Append(_separatorForKeyValue); sb.Append(pair.Value.MaxCount); sb.Append(_separatorForKeyValue); foreach (T? item in pair.Value.GetItems()) { string data = item?.GetDataForSave() ?? string.Empty; if (string.IsNullOrEmpty(data)) { continue; } sb.Append(data); sb.Append(_separatorItems); } } using FileStream fs = new(filename, FileMode.Create); byte[] info = new UTF8Encoding(true).GetBytes(sb.ToString()); fs.Write(info, 0, info.Length); } // Создание коллекции по типу private static ICollectionGenObj? CreateCollection(CollectionType collectionType) { return collectionType switch { CollectionType.Array => new ArrayGenObj(), CollectionType.List => new ListGenObj(), _ => null, }; } // Загрузка информации по кораблям в хранилище из файла public void LoadData(string filename) { if (!File.Exists(filename)) throw new FileNotFoundException(); string bufferTextFromFile = ""; using (FileStream fs = new(filename, FileMode.Open)) { byte[] b = new byte[fs.Length]; UTF8Encoding temp = new(true); while (fs.Read(b, 0, b.Length) > 0) { bufferTextFromFile += temp.GetString(b); } } string[] strs = bufferTextFromFile.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); if (strs == null || strs.Length == 0) throw new NullReferenceException("> No data to decode"); if (!strs[0].Equals(_collectionKey)) throw new InvalidDataException("> Incorrect data"); string[] companies = new string[strs.Length - 1]; for (int k = 1; k < strs.Length; k++) { companies[k - 1] = strs[k]; } _storages.Clear(); foreach (string data in companies) { string[] record = data.Split(_separatorForKeyValue, StringSplitOptions.RemoveEmptyEntries); if (record.Length != 4) // > // key | collType | maxcount | all next inf > 4 { continue; } CollectionType collectionType = (CollectionType)Enum.Parse(typeof(CollectionType), record[1]); ICollectionGenObj? collection = StorageCollection.CreateCollection(collectionType); if (collection == null) throw new NullReferenceException("> Failed to create collection"); collection.MaxCount = Convert.ToInt32(record[2]); string[] set = record[3].Split(_separatorItems, StringSplitOptions.RemoveEmptyEntries); foreach (string elem in set) { if (elem?.CreateDrawningCar() is T ship) { try { if (collection.Insert(ship) == -1) throw new IndexOutOfRangeException( "> Failed to add to collection : " + record[3]); } catch (CollectionOverflowException e) { throw new CollectionOverflowException("Collection overflowed", e); } } } _storages.Add(record[0], collection); } } }