public EmbeddedBlobStore([NotNull] Assembly assembly, StringKeySequence basePath = default(StringKeySequence)) { if (assembly == null) { throw new ArgumentNullException(nameof(assembly)); } mData = CreateHierarchicalStoreFromManifestResourceNames(assembly, basePath); }
private EmbeddedBlobStoreNamespace CreateHierarchicalStoreFromManifestResourceNames(Assembly assembly, StringKeySequence basePath) { var resourceNames = assembly.GetManifestResourceNames(); var baseName = assembly.DefinedTypes .Select(x => x.Namespace) .Where(x => !string.IsNullOrEmpty(x)) .Distinct() .Where(x => resourceNames.Any(y => y.StartsWith(x))) .OrderBy(x => x.Length) .FirstOrDefault(); if (!basePath.IsEmpty) { baseName += "." + basePath.ToString("."); } StringKeySequence rootName; if (string.IsNullOrWhiteSpace(baseName)) { rootName = new StringKeySequence(); } else { rootName = new StringKeySequence(baseName.Split('.')); } var names = new HashSet <StringKeySequence>(resourceNames.Select(x => CreateKeySequence(baseName, x)).OrderBy(x => x.Segments.Length)); if (names.Count == 0) { return(new EmbeddedBlobStoreNamespace(rootName, new StringKeySequence(), assembly, new Dictionary <StringKey, EmbeddedBlobStoreNamespace>(), new StringKey[0])); } var leafNames = new HashSet <StringKeySequence>( from ancestor in names let directDescendants = from descendant in names let isNextLevelDescendant = descendant.Segments.Length == ancestor.Segments.Length + 1 let isDescendantInAncestorSet = descendant.ToString().StartsWith(ancestor.ToString()) where isNextLevelDescendant && isDescendantInAncestorSet select descendant where !directDescendants.Any() select ancestor); var branchNames = new HashSet <StringKeySequence>(); foreach (var leafName in leafNames) { for (var i = 0; i < leafName.Segments.Length - 1; i++) { var partialName = new StringKeySequence(leafName.Segments.Take(i + 1).ToArray()); branchNames.Add(partialName); } } if (branchNames.Count == 0) { return(new EmbeddedBlobStoreNamespace(rootName, new StringKeySequence(), assembly, new Dictionary <StringKey, EmbeddedBlobStoreNamespace>(), leafNames.Select(x => x.ToString(".").AsKey()))); } var structure = from branch in branchNames let childBranches = from childBranch in branchNames let isNextLevelDescendant = childBranch.Segments.Length == branch.Segments.Length + 1 let isDescendantInAncestorSet = childBranch.ToString().StartsWith(branch.ToString()) where isNextLevelDescendant && isDescendantInAncestorSet select childBranch let childLeaves = from childLeaf in leafNames let isNextLevelDescendant = childLeaf.Segments.Length == branch.Segments.Length + 1 let isDescendantInAncestorSet = childLeaf.ToString().StartsWith(branch.ToString()) where isNextLevelDescendant && isDescendantInAncestorSet select childLeaf let sortKey = childBranches.Any() ? 0 : 1 let level = branch.Segments.Length // ReSharper disable once RedundantQueryOrderByAscendingKeyword orderby sortKey ascending // ReSharper disable once MultipleOrderBy orderby level descending select new { Name = branch, Branches = childBranches, Leaves = childLeaves, Level = level }; var branchDictionary = new Dictionary <StringKeySequence, EmbeddedBlobStoreNamespace>(); foreach (var element in structure) { var directChildren = element.Branches.ToDictionary(x => x.Segments.Last(), x => branchDictionary[x]); var childLeaves = element.Leaves.Select(x => x.Segments.Last()).ToArray(); var container = new EmbeddedBlobStoreNamespace(rootName, element.Name, assembly, directChildren, childLeaves); branchDictionary.Add(element.Name, container); } var minLength = branchDictionary.Min(x => x.Key.Segments.Length); var bottomLevelBranches = branchDictionary.Where(x => x.Key.Segments.Length == minLength); var bottomLevelLeaves = leafNames.Where(x => x.Segments.Length == minLength); return(new EmbeddedBlobStoreNamespace( rootName, new StringKeySequence(), assembly, bottomLevelBranches.ToDictionary(x => x.Key.Segments.Last(), x => x.Value), bottomLevelLeaves.Select(x => x.Segments.Last()))); }