예제 #1
0
        public EmbeddedBlobStore([NotNull] Assembly assembly, StringKeySequence basePath = default(StringKeySequence))
        {
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            mData = CreateHierarchicalStoreFromManifestResourceNames(assembly, basePath);
        }
예제 #2
0
        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())));
        }