public void DetectMinimumCircularDependencyBetweenTwoNodes()
        {
            var a = new Node {
                Name = "A"
            };
            var b = new Node {
                Name = "B"
            };

            a.Edges.Add(b);
            b.Edges.Add(a);

            var roots = new Roots();

            roots.Entangle(a);

            var serializers = new Serializers(new SerializerFactory());
            var stateMaps   = new StateMaps(serializers);
            var persister   = new Persister(new InMemoryStorageEngine(), roots, serializers, stateMaps);

            persister.DetectSerializeAndPersistChanges();

            var circularChain = CircularDependencyDetector.Check(serializers[0], stateMaps, serializers);

            circularChain.IsCircular.ShouldBeTrue();
            circularChain.Path.Count().ShouldBe(3);
            circularChain.ToString().ShouldBe("A->B->A");
        }
        public void DetectCircularDependencyInComplexGraph()
        {
            var a = new Node {
                Name = "A"
            };
            var b = new Node {
                Name = "B"
            };
            var c = new Node {
                Name = "C"
            };
            var d = new Node {
                Name = "D"
            };
            var e = new Node {
                Name = "E"
            };
            var f = new Node {
                Name = "F"
            };
            var g = new Node {
                Name = "G"
            };
            var h = new Node {
                Name = "H"
            };

            a.Add(b);
            a.Add(c);

            c.Add(g);
            c.Add(f);

            g.Add(b);

            b.Add(d);

            d.Add(h);

            d.Add(f);
            f.Add(e);
            e.Add(d);

            var roots = new Roots();

            roots.Entangle(a);

            var serializers = new Serializers(new SerializerFactory());
            var stateMaps   = new StateMaps(serializers);
            var persister   = new Persister(new InMemoryStorageEngine(), roots, serializers, stateMaps);

            persister.DetectSerializeAndPersistChanges();

            var circularChain = CircularDependencyDetector.Check(serializers[0], stateMaps, serializers);

            circularChain.IsCircular.ShouldBe(true);
            circularChain.Path.Count().ShouldBe(4);
            circularChain.ToString().ShouldBe("F->E->D->F");
        }
        private void GenerateBaseExpression(ServiceBinding serviceBinding, CircularDependencyDetector circularDependencyDetector)
        {
            if (serviceBinding.BaseExpression == null)
            {
                lock (serviceBinding)
                {
                    if (serviceBinding.BaseExpression == null)
                    {
                        if (serviceBinding.Expression == null)
                        {
                            var constructor = serviceBinding.ConstructorResolver.DynamicSelectConstructor(serviceBinding.ConcreteType, this);
                            serviceBinding.Expression = serviceBinding.ConcreteType.ResolveConstructorExpression(constructor);
                        }
                        ParameterExpression[] parameters = serviceBinding.Expression.GetParameterExpressions().Where(x => x.Type != ExpressionGenerator.ScopeParameter.Type).ToArray();
                        InstanceFactory[]     factories  = ResolveParameters(parameters, circularDependencyDetector);

                        serviceBinding.BaseExpression = _expressionGenerator.GenerateBaseExpression(serviceBinding, factories, _containerScope, Settings);
                    }
                }
            }
        }
Beispiel #4
0
        public void DetectSerializeAndPersistChanges(bool checkForCircularDependencies = false)
        {
            var detectedChanges = DetectChanges();

            if (detectedChanges.GarbageCollectableIds.Empty() &&
                detectedChanges.RemovedEntries.Empty() &&
                detectedChanges.NewEntries.Empty())
            {
                return;
            }

            if (checkForCircularDependencies)
            {
                var(isCircular, path) = CircularDependencyDetector.Check(root: _serializers[0], _stateMaps, _serializers);
                if (isCircular)
                {
                    throw new CircularDependencyException(path);
                }
            }

            _storageEngine.Persist(detectedChanges);
        }
        public void DetectCircularDependencyOneNodeHavingMultipleOutgoingEdges()
        {
            var a = new Node {
                Name = "A"
            };
            var b = new Node {
                Name = "B"
            };
            var c = new Node {
                Name = "C"
            };
            var d = new Node {
                Name = "D"
            };

            a.Edges.Add(b);
            a.Edges.Add(d);
            b.Edges.Add(c);
            c.Edges.Add(b);

            var roots = new Roots();

            roots.Entangle(a);

            var serializers = new Serializers(new SerializerFactory());
            var stateMaps   = new StateMaps(serializers);
            var persister   = new Persister(new InMemoryStorageEngine(), roots, serializers, stateMaps);

            persister.DetectSerializeAndPersistChanges();

            var circularChain = CircularDependencyDetector.Check(serializers[0], stateMaps, serializers);

            circularChain.IsCircular.ShouldBeTrue();
            circularChain.Path.Count().ShouldBe(3);
            circularChain.ToString().ShouldBe("B->C->B");
        }
        public void ThrowOnCircularDependency_throws_exception_when_there_is_a_circular_dependency(IServiceRegistration registration1,
                                                                                                   IServiceRegistration registration2,
                                                                                                   IServiceRegistration registration3,
                                                                                                   CircularDependencyDetector sut)
        {
            // Arrange
            var path = new ResolutionPath(new [] { registration1, registration2, registration3 });

            // Act & assert
            Assert.That(() => sut.ThrowOnCircularDependency(registration2, path),
                        Throws.InstanceOf <CircularDependencyException>());
        }
        public void ThrowOnCircularDependency_does_not_throw_when_there_is_no_circular_dependency(IServiceRegistration registration1,
                                                                                                  IServiceRegistration registration2,
                                                                                                  IServiceRegistration registration3,
                                                                                                  CircularDependencyDetector sut)
        {
            // Arrange
            var path = new ResolutionPath(new [] { registration1, registration2 });

            // Act & assert
            Assert.That(() => sut.ThrowOnCircularDependency(registration3, path), Throws.Nothing);
        }
        public void HasCircularDependency_returns_true_when_there_is_a_circular_dependency(IServiceRegistration registration1,
                                                                                           IServiceRegistration registration2,
                                                                                           IServiceRegistration registration3,
                                                                                           CircularDependencyDetector sut)
        {
            // Arrange
            var path = new ResolutionPath(new [] { registration1, registration2, registration3 });

            // Act
            var result = sut.HasCircularDependency(registration2, path);

            // Assert
            Assert.That(result, Is.True);
        }
        private InstanceFactory[] ResolveParameters(ParameterExpression[] parameters, CircularDependencyDetector circularDependencyDetector)
        {
            var factories = new InstanceFactory[parameters.Length];

            for (var i = 0; i < parameters.Length; i++)
            {
                ParameterExpression parameter = parameters[i];
                ServiceBinding      child     = GetDependency(parameter.Type).Default;
                InstanceFactory?    factory   = TryResolveDependency(parameter.Type, child, circularDependencyDetector);
                factories[i] = factory ?? throw (child.ResolveError ?? throw new NotImplementedException());
            }

            return(factories);
        }
 private InstanceFactory GenerateInstanceFactory(Type type, ServiceBinding serviceBinding, CircularDependencyDetector circularDependencyDetector)
 {
     lock (serviceBinding)
     {
         if (!serviceBinding.TryGetInstanceFactory(type, out InstanceFactory factory))
         {
             Expression[]              decorators = FindDecorators(type);
             ParameterExpression[]     parameters = decorators.GetParameterExpressions().Where(x => x.Type != ExpressionGenerator.ScopeParameter.Type && x.Type != type).ToArray();
             InstanceFactory[]         factories  = ResolveParameters(parameters, circularDependencyDetector);
             ReadOnlyExpressionContext context    = _expressionGenerator.ApplyDecorators(type, serviceBinding, factories, decorators, _containerScope);
             factory = new InstanceFactory(type, context);
             serviceBinding.Factories.Add(factory);
         }
         return(factory);
     }
 }
 private InstanceFactory?TryResolveDependency(Type type, ServiceBinding dependency, CircularDependencyDetector circularDependencyDetector)
 {
     try
     {
         Settings.Logger.Log($"{nameof(TryResolveDependency)} for {type}", circularDependencyDetector.Count);
         circularDependencyDetector.Enter(type);
         if (type.IsGenericType && type.ContainsGenericParameters)
         {
             throw new OpenGenericTypeResolveException($"Cannot create a instance for type {type} since its registered as a abstract binding and not meant to be used directly.");
         }
         GenerateBaseExpression(dependency, circularDependencyDetector);
         InstanceFactory factory = GenerateInstanceFactory(type, dependency, circularDependencyDetector);
         return(factory);
     }
     catch (Exception e)
     {
         dependency.ResolveError = new DependencyResolveException(type, dependency, e);
         return(null);
     }
     finally
     {
         circularDependencyDetector.Leave(type);
     }
 }