public void Should_CreateSpecificationScope_And_SaveType_And_ReturnIds_For_DifferentSpecifications()
            {
                var context = new ScopeBuilderContext();

                Specification <object>    specification1 = m => m;
                Specification <DateTime?> specification2 = m => m;
                Specification <int>       specification3 = m => m;

                var specificationScopeId1 = context.GetOrRegisterSpecificationScope(specification1);
                var specificationScopeId2 = context.GetOrRegisterSpecificationScope(specification2);
                var specificationScopeId3 = context.GetOrRegisterSpecificationScope(specification3);

                specificationScopeId1.Should().Be(0);
                specificationScopeId2.Should().Be(1);
                specificationScopeId3.Should().Be(2);

                context.Scopes.Should().NotBeEmpty();
                context.Scopes.Count.Should().Be(3);

                context.Scopes.Keys.Should().Contain(specificationScopeId1);
                context.Scopes[specificationScopeId1].Should().BeOfType <SpecificationScope <object> >();

                context.Scopes.Keys.Should().Contain(specificationScopeId2);
                context.Scopes[specificationScopeId2].Should().BeOfType <SpecificationScope <DateTime?> >();

                context.Scopes.Keys.Should().Contain(specificationScopeId3);
                context.Scopes[specificationScopeId3].Should().BeOfType <SpecificationScope <int> >();

                context.Types.Should().NotBeEmpty();
                context.Types.Count.Should().Be(3);
                context.Types[specificationScopeId1].Should().Be(typeof(object));
                context.Types[specificationScopeId2].Should().Be(typeof(DateTime?));
                context.Types[specificationScopeId3].Should().Be(typeof(int));
            }
        public static ModelScheme <T> Create <T>(Specification <T> specification, ICapacityInfo capacityInfo)
        {
            ThrowHelper.NullArgument(specification, nameof(specification));

            var scopeBuilderContext = new ScopeBuilderContext();

            var rootSpecificationScopeId = scopeBuilderContext.GetOrRegisterSpecificationScope(specification);

            var discoveryContext = new DiscoveryContext(scopeBuilderContext, rootSpecificationScopeId);

            var rootSpecificationScope = (SpecificationScope <T>)scopeBuilderContext.Scopes[rootSpecificationScopeId];

            rootSpecificationScope.Discover(discoveryContext);

            if (capacityInfo is ICapacityInfoHelpersConsumer capacityInfoHelpersConsumer)
            {
                capacityInfoHelpersConsumer.InjectHelpers(CapacityInfoHelpers);
            }

            if (capacityInfo is IFeedableCapacityInfo feedableCapacityInfo && feedableCapacityInfo.ShouldFeed)
            {
                feedableCapacityInfo.Feed(discoveryContext);
            }

            return(new ModelScheme <T>(
                       scopeBuilderContext.Scopes,
                       rootSpecificationScopeId,
                       scopeBuilderContext.Errors,
                       discoveryContext.Errors.ToDictionary(p => p.Key, p => (IReadOnlyList <int>)p.Value),
                       discoveryContext.Paths.ToDictionary(p => p.Key, p => (IReadOnlyDictionary <string, string>)p.Value),
                       capacityInfo,
                       discoveryContext.ReferenceLoopRoots.Count > 0));
        }
            public void Should_ThrowException_When_NullSpecification()
            {
                var context = new ScopeBuilderContext();

                Action action = () => context.GetOrRegisterSpecificationScope <object>(null);

                action.Should().ThrowExactly <ArgumentNullException>();
            }
            public void Should_GetSpecificationScope()
            {
                var context = new ScopeBuilderContext();

                Specification <TestClass> specification = m => m;

                var specificationScopeId = context.GetOrRegisterSpecificationScope(specification);

                var discoverableSpecificationScope = context.GetDiscoverableSpecificationScope(specificationScopeId);

                discoverableSpecificationScope.Should().BeSameAs(context.Scopes[specificationScopeId]);
            }
            public void Should_CreateSpecificationScope_And_SaveType_OnlyOnce_For_MultipleCallsWithSameSpecification()
            {
                var context = new ScopeBuilderContext();

                Specification <object> specification = m => m;

                var specificationScopeId1 = context.GetOrRegisterSpecificationScope(specification);
                var specificationScopeId2 = context.GetOrRegisterSpecificationScope(specification);
                var specificationScopeId3 = context.GetOrRegisterSpecificationScope(specification);

                specificationScopeId1.Should().Be(0);
                specificationScopeId2.Should().Be(0);
                specificationScopeId3.Should().Be(0);

                context.Scopes.Should().NotBeEmpty();
                context.Scopes.Count.Should().Be(1);

                context.Scopes.Keys.Should().Contain(specificationScopeId1);
                context.Scopes[specificationScopeId1].Should().BeOfType <SpecificationScope <object> >();

                context.Types.Should().NotBeEmpty();
                context.Types.Count.Should().Be(1);
                context.Types[specificationScopeId1].Should().Be(typeof(object));
            }
            public void Should_CreateSpecificationScope_And_SaveType_And_ReturnItsId()
            {
                var context = new ScopeBuilderContext();

                Specification <TestClass> specification = m => m;

                var specificationScopeId = context.GetOrRegisterSpecificationScope(specification);

                specificationScopeId.Should().Be(0);

                context.Scopes.Should().NotBeEmpty();
                context.Scopes.Count.Should().Be(1);
                context.Scopes.Keys.Should().Contain(specificationScopeId);

                context.Scopes[specificationScopeId].Should().BeOfType <SpecificationScope <TestClass> >();

                context.Types.Should().NotBeEmpty();
                context.Types.Count.Should().Be(1);
                context.Types[specificationScopeId].Should().Be(typeof(TestClass));
            }
        public static IModelScheme <T> Create <T>(Specification <T> specification)
        {
            ThrowHelper.NullArgument(specification, nameof(specification));

            var scopeBuilderContext = new ScopeBuilderContext();

            var rootSpecificationScopeId = scopeBuilderContext.GetOrRegisterSpecificationScope(specification);

            var discoveryContext = new DiscoveryContext(scopeBuilderContext, rootSpecificationScopeId);

            var rootSpecificationScope = (SpecificationScope <T>)scopeBuilderContext.Scopes[rootSpecificationScopeId];

            rootSpecificationScope.Discover(discoveryContext);

            return(new ModelScheme <T>(
                       scopeBuilderContext.Scopes,
                       rootSpecificationScopeId,
                       scopeBuilderContext.Errors,
                       discoveryContext.Errors.ToDictionary(p => p.Key, p => (IReadOnlyList <int>)p.Value),
                       discoveryContext.Paths.ToDictionary(p => p.Key, p => (IReadOnlyDictionary <string, string>)p.Value),
                       discoveryContext.ReferenceLoopRoots.Count > 0));
        }