/// <summary> Can also be safely called for reloads. </summary> public async Task Load() { try { HolzShotsPaths.EnsureDirectory(_customUploadersDirectory); // var res = new Dictionary<UploaderMeta, CustomUploader>(); var res = ImmutableDictionary.CreateBuilder <UploaderMeta, CustomUploader>(); var files = ImmutableDictionary.CreateBuilder <string, CustomUploaderSpec>(); foreach (var jsonFile in Directory.EnumerateFiles(_customUploadersDirectory, HolzShotsPaths.CustomUploadersFilePattern)) { using var reader = File.OpenText(jsonFile); var jsonStr = await reader.ReadToEndAsync().ConfigureAwait(false); // TODO: Catch parsing errors var uploader = JsonConvert.DeserializeObject <CustomUploaderSpec>(jsonStr, JsonConfig.JsonSettings); // TODO: Aggregate errors of invalid files (and display them to the user) Debug.Assert(uploader != null); if (CustomUploader.TryLoad(uploader, out var loadedUploader)) { Debug.Assert(loadedUploader != null); res.Add(uploader.Meta, loadedUploader); files.Add(jsonFile, uploader); } } _uploadersFiles = files.ToImmutable(); _customUploaders = res.ToImmutable(); } catch (FileNotFoundException) { _customUploaders = ImmutableDictionary <UploaderMeta, CustomUploader> .Empty; } finally { Loaded = true; } }