private static string BuildRelationshipDescription(KnownRelationship relationship) { string additionalInformation1 = relationship.GetAdditionalInformation(DiagnosticType.LifestyleMismatch); string additionalInformation2 = relationship.Dependency.Registration is ScopedRegistration scoped ? scoped.AdditionalInformationForLifestyleMismatchDiagnostics : string.Empty; return(string.Format( CultureInfo.InvariantCulture, "{0} ({1}) depends on {2}{3} ({4}).{5}{6}{7}{8}", relationship.ImplementationType.FriendlyName(), relationship.Lifestyle.Name, relationship.Dependency.ServiceType.FriendlyName(), relationship.Dependency.ServiceType != relationship.Dependency.FinalImplementationType ? " implemented by " + relationship.Dependency.FinalImplementationType.FriendlyName() : string.Empty, relationship.Dependency.Lifestyle.Name, additionalInformation1 == string.Empty ? string.Empty : " ", additionalInformation1, additionalInformation2 == string.Empty ? string.Empty : " ", additionalInformation2)); }
public void KnownRelationships_InsertingNullValue_ThrowsExpectedException() { // Arrange KnownRelationship invalidRelationship = null; var container = ContainerFactory.New(); container.Register <IUserRepository, SqlUserRepository>(); container.Register <FakeUserService>(); container.ExpressionBuilt += (s, e) => { if (e.RegisteredServiceType == typeof(FakeUserService)) { Assert.AreEqual(1, e.KnownRelationships.Count, "Test setup failed."); // Assert AssertThat.Throws <ArgumentNullException>( () => e.KnownRelationships.Insert(0, invalidRelationship)); } }; // Act container.GetInstance <FakeUserService>(); }
internal LifestyleMismatchDiagnosticResult(Type serviceType, string description, KnownRelationship relationship) : base(serviceType, description, DiagnosticType.LifestyleMismatch, DiagnosticSeverity.Warning, relationship) { this.Relationship = relationship; }
private static string BuildDescription(InstanceProducer registration, KnownRelationship[] relationships) { string componentName = BuildComponentName(registration, relationships); string unregisteredTypeName = BuildUnregisteredTypeDescription(relationships); return componentName + " depends on " + unregisteredTypeName + "."; }
internal static bool HasLifestyleMismatch(Container container, KnownRelationship relationship) { Lifestyle componentLifestyle = relationship.Lifestyle; Lifestyle dependencyLifestyle = relationship.Dependency.Lifestyle; // If the lifestyles are the same instance, we consider them valid, even though in theory // an hybrid lifestyle could screw things up. In practice this would be very unlikely, since // the Func<bool> test delegate would typically return the same value within a given context. if (object.ReferenceEquals(componentLifestyle, dependencyLifestyle) && componentLifestyle != Lifestyle.Unknown) { return(false); } var componentLength = componentLifestyle.ComponentLength(container); if (container.Options.UseLoosenedLifestyleMismatchBehavior && componentLength <= Lifestyle.Scoped.Length) { return(false); } var dependencyLength = dependencyLifestyle.DependencyLength(container); return(componentLength > dependencyLength); }
private KnownRelationship ReplaceLifestyle(KnownRelationship relationship) { return(new KnownRelationship( relationship.ImplementationType, this.Lifestyle, relationship.Dependency)); }
public void GetRelationship_OnRegistrationBuiltByRegisterAllOpenGeneric_ReturnsTheExpectedRelationships() { // Arrange var container = ContainerFactory.New(); container.RegisterSingle <ILogger, FakeLogger>(); container.RegisterAllOpenGeneric(typeof(IEventHandler <>), typeof(EventHandlerWithLoggerDependency <>)); container.Register <ServiceWithDependency <IEnumerable <IEventHandler <ClassEvent> > > >(); container.Verify(); var expectedRelationship = new KnownRelationship( implementationType: typeof(EventHandlerWithLoggerDependency <ClassEvent>), lifestyle: Lifestyle.Transient, dependency: container.GetRegistration(typeof(ILogger))); // Act var actualRelationship = container.GetRegistration(typeof(IEnumerable <IEventHandler <ClassEvent> >)).GetRelationships() .Single(); // Assert Assert.AreEqual(expectedRelationship.ImplementationType, actualRelationship.ImplementationType); Assert.AreEqual(expectedRelationship.Lifestyle, actualRelationship.Lifestyle); Assert.AreEqual(expectedRelationship.Dependency, actualRelationship.Dependency); }
private KnownRelationship ReplaceLifestyle(KnownRelationship relationship) => new KnownRelationship( relationship.ImplementationType, this.Lifestyle, relationship.Consumer, relationship.Dependency, relationship.AdditionalInformation);
private static ContainerRegisteredServiceDiagnosticResult BuildDiagnosticResult( InstanceProducer registration, KnownRelationship[] relationships) { return new ContainerRegisteredServiceDiagnosticResult( serviceType: registration.ServiceType, description: BuildDescription(registration, relationships), relationships: relationships); }
internal void AddRelationship(KnownRelationship relationship) { Requires.IsNotNull(relationship, "relationship"); lock (this.dependencies) { this.dependencies.Add(relationship); } }
internal void AddRelationship(KnownRelationship relationship) { Requires.IsNotNull(relationship, nameof(relationship)); lock (this.knownRelationships) { this.knownRelationships.Add(relationship); } }
private static string BuildRelationshipDescription(KnownRelationship relationship) { return(string.Format(CultureInfo.InvariantCulture, "{0} ({1}) depends on {2} ({3}).", Helpers.ToFriendlyName(relationship.ImplementationType), relationship.Lifestyle.Name, Helpers.ToFriendlyName(relationship.Dependency.ServiceType), relationship.Dependency.Lifestyle.Name)); }
private static string BuildRelationshipDescription(KnownRelationship relationship) => string.Format(CultureInfo.InvariantCulture, "{0} ({1}) depends on {2}{3} ({4}).", relationship.ImplementationType.ToFriendlyName(), relationship.Lifestyle.Name, relationship.Dependency.ServiceType.ToFriendlyName(), relationship.Dependency.ServiceType != relationship.Dependency.ImplementationType ? " implemented by " + relationship.Dependency.ImplementationType.ToFriendlyName() : string.Empty, relationship.Dependency.Lifestyle.Name);
private static string BuildRelationshipDescription(KnownRelationship relationship) => string.Format(CultureInfo.InvariantCulture, "{0} ({1}) depends on {2}{3} ({4}).", Helpers.ToFriendlyName(relationship.ImplementationType), relationship.Lifestyle.Name, Helpers.ToFriendlyName(relationship.Dependency.ServiceType), relationship.Dependency.ServiceType != relationship.Dependency.ImplementationType ? " implemented by " + Helpers.ToFriendlyName(relationship.Dependency.ImplementationType) : string.Empty, relationship.Dependency.Lifestyle.Name);
internal ShortCircuitedDependencyDiagnosticResult(Type serviceType, string description, InstanceProducer registration, KnownRelationship relationship, IEnumerable<InstanceProducer> expectedDependencies) : base(serviceType, description, DiagnosticType.ShortCircuitedDependency, DiagnosticSeverity.Warning, CreateDebugValue(registration, relationship, expectedDependencies.ToArray())) { this.Relationship = relationship; this.ExpectedDependencies = new ReadOnlyCollection<InstanceProducer>(expectedDependencies.ToList()); }
internal static bool HasLifestyleMismatch(Container container, KnownRelationship relationship) { Lifestyle componentLifestyle = relationship.Lifestyle; Lifestyle dependencyLifestyle = relationship.Dependency.Lifestyle; // If the lifestyles are the same instance, we consider them valid, even though in theory // an hybrid lifestyle could screw things up. In practice this would be very unlikely, since // the Func<bool> test delegate would typically return the same value within a given context. if (object.ReferenceEquals(componentLifestyle, dependencyLifestyle) && componentLifestyle != Lifestyle.Unknown) { return false; } return componentLifestyle.ComponentLength(container) > dependencyLifestyle.DependencyLength(container); }
internal static bool HasPossibleLifestyleMismatch(KnownRelationship relationship) { Lifestyle componentLifestyle = relationship.Lifestyle; Lifestyle dependencyLifestyle = relationship.Dependency.Lifestyle; // If the lifestyles are the same instance, we consider them valid, even though in theory // an hybrid lifestyle could screw things up. In practice this would be very unlikely, since // the Func<bool> test delegate would typically return the same value within a given context. if (object.ReferenceEquals(componentLifestyle, dependencyLifestyle) && componentLifestyle != Lifestyle.Unknown) { return(false); } return(componentLifestyle.ComponentLength > dependencyLifestyle.DependencyLength); }
public void KnownRelationships_AddingNullValue_ThrowsExpectedException() { // Arrange KnownRelationship invalidRelationship = null; var container = ContainerFactory.New(); container.ExpressionBuilt += (s, e) => { // Assert AssertThat.Throws <ArgumentNullException>(() => e.KnownRelationships.Add(invalidRelationship)); }; // Act container.GetInstance <SqlUserRepository>(); }
private static string BuildDescription(KnownRelationship relationship, IEnumerable <InstanceProducer> possibleSkippedRegistrations) { var possibleSkippedRegistrationsDescription = string.Join(" or ", from possibleSkippedRegistration in possibleSkippedRegistrations let name = possibleSkippedRegistration.ServiceType.ToFriendlyName() orderby name select string.Format(CultureInfo.InvariantCulture, "{0} ({1})", name, possibleSkippedRegistration.Lifestyle.Name)); return(string.Format(CultureInfo.InvariantCulture, "{0} might incorrectly depend on unregistered type {1} ({2}) instead of {3}.", relationship.ImplementationType.ToFriendlyName(), relationship.Dependency.ServiceType.ToFriendlyName(), relationship.Dependency.Lifestyle.Name, possibleSkippedRegistrationsDescription)); }
protected InstanceProducer CreateDecorateeFactoryProducer( ParameterInfo parameter, InstanceProducer decorateeProducer) { // We create a dummy expression with a null value. Much easier than passing on the real delegate. // We won't miss it, since the created InstanceProducer is just a dummy for purposes of analysis. var dummyExpression = Expression.Constant(null, parameter.ParameterType); var registration = new ExpressionRegistration(dummyExpression, this.Container); var relationship = new KnownRelationship( parameter.ParameterType, Lifestyle.Singleton, decorateeProducer) { // Make sure the relationship is not traversed when doing verification, because that leads to // false positivies. UseForVerification = false }; registration.AddRelationship(relationship); return(new InstanceProducer(parameter.ParameterType, registration)); }
private static DebuggerViewItem[] CreateDebugValue(InstanceProducer registration, KnownRelationship actualDependency, InstanceProducer[] possibleSkippedRegistrations) { return new[] { new DebuggerViewItem( name: "Registration", description: registration.ServiceType.ToFriendlyName(), value: registration), new DebuggerViewItem( name: "Actual Dependency", description: actualDependency.Dependency.ServiceType.ToFriendlyName(), value: actualDependency), new DebuggerViewItem( name: "Expected Dependency", description: possibleSkippedRegistrations.First().ServiceType.ToFriendlyName(), value: possibleSkippedRegistrations.Length == 1 ? (object)possibleSkippedRegistrations[0] : possibleSkippedRegistrations), }; }
private static DebuggerViewItem[] CreateDebugValue(InstanceProducer registration, KnownRelationship actualDependency, InstanceProducer[] possibleSkippedRegistrations) { return(new[] { new DebuggerViewItem( name: "Registration", description: registration.ServiceType.ToFriendlyName(), value: registration), new DebuggerViewItem( name: "Actual Dependency", description: actualDependency.Dependency.ServiceType.ToFriendlyName(), value: actualDependency), new DebuggerViewItem( name: "Expected Dependency", description: possibleSkippedRegistrations[0].ServiceType.ToFriendlyName(), value: possibleSkippedRegistrations.Length == 1 ? (object)possibleSkippedRegistrations[0] : possibleSkippedRegistrations), }); }
private Action <ServiceCreatedListenerArgs> CreateCollectionUsedDuringConstructionListener( ThreadLocal <bool> isCurrentThread) { return(args => { // Only handle when an inner registration hasn't handled this yet. if (!args.Handled) { // Only handle when the call originates from the same thread, as calls from different // threads mean the listener is not triggered from this specific instanceCreator. if (isCurrentThread.Value) { args.Handled = true; var matchingRelationship = this.FindMatchingCollectionRelationship(args.Producer); var additionalInformation = StringResources.CollectionUsedDuringConstruction( this.ImplementationType, args.Producer, matchingRelationship); // At this point, an injected ContainerControlledCollection<T> has notified the // listener about the creation of one of its elements. This has happened during // the construction of this (Singleton) instance, which might cause Lifestyle // Mismatches. That's why this is added as a known relationship. This way // diagnostics can verify the relationship. var relationship = new KnownRelationship( implementationType: this.ImplementationType, lifestyle: this.Lifestyle, consumer: matchingRelationship?.Consumer ?? InjectionConsumerInfo.Root, dependency: args.Producer); relationship.AddAdditionalInformation( DiagnosticType.LifestyleMismatch, additionalInformation); this.AddRelationship(relationship); } } }); }
private static bool HasPossibleLifestyleMismatch(KnownRelationship dependency) => LifestyleMismatchChecker.HasLifestyleMismatch(new Container(), dependency);
internal PotentialLifestyleMismatchDiagnosticResult(Type serviceType, string description, KnownRelationship relationship) : base(serviceType, description, DiagnosticType.PotentialLifestyleMismatch, relationship) { this.Relationship = relationship; }
private KnownRelationship ReplaceLifestyle(KnownRelationship relationship) => new KnownRelationship( relationship.ImplementationType, this.Lifestyle, relationship.Dependency);
private void MarkDecorateeFactoryRelationshipAsInstanceCreationDelegate( KnownRelationship[] relationships) { var decorateeFactoryDependencies = this.GetDecorateeFactoryDependencies(relationships); foreach (Registration dependency in decorateeFactoryDependencies) { // Mark the dependency of the decoratee factory dependency.WrapsInstanceCreationDelegate = true; } }
private IEnumerable<Registration> GetDecorateeFactoryDependencies(KnownRelationship[] relationships) => from relationship in relationships where DecoratorHelpers.IsDecorateeFactoryDependencyParameter( relationship.Dependency.ServiceType, this.e.RegisteredServiceType) select relationship.Dependency.Registration;
private static bool HasPossibleLifestyleMismatch( KnownRelationship dependency, bool?useLoosenedLifestyleMismatchBehavior = null) => LifestyleMismatchChecker.HasLifestyleMismatch( CreateContainer(useLoosenedLifestyleMismatchBehavior), dependency);
private static string BuildDescription(KnownRelationship relationship, IEnumerable<InstanceProducer> possibleSkippedRegistrations) { var possibleSkippedRegistrationsDescription = string.Join(" or ", from possibleSkippedRegistration in possibleSkippedRegistrations let name = possibleSkippedRegistration.ServiceType.ToFriendlyName() orderby name select string.Format(CultureInfo.InvariantCulture, "{0} ({1})", name, possibleSkippedRegistration.Lifestyle.Name)); return string.Format(CultureInfo.InvariantCulture, "{0} might incorrectly depend on unregistered type {1} ({2}) instead of {3}.", relationship.ImplementationType.ToFriendlyName(), relationship.Dependency.ServiceType.ToFriendlyName(), relationship.Dependency.Lifestyle.Name, possibleSkippedRegistrationsDescription); }
private static string BuildComponentName(InstanceProducer registration, KnownRelationship[] relationships) { var consumingTypes = ( from relationship in relationships select relationship.ImplementationType) .Distinct() .ToArray(); if (consumingTypes.Length == 1) { return consumingTypes.First().ToFriendlyName(); } else { return registration.ServiceType.ToFriendlyName(); } }
private static string BuildUnregisteredTypeDescription(KnownRelationship[] relationships) { var unregisteredTypes = ( from relationship in relationships select relationship.Dependency.ServiceType) .Distinct() .ToArray(); if (unregisteredTypes.Length == 1) { return "container-registered type " + unregisteredTypes[0].ToFriendlyName(); } else { return unregisteredTypes.Length + " container-registered types"; } }