diff --git a/src/LightInject.Tests/ServiceRegistrationTests.cs b/src/LightInject.Tests/ServiceRegistrationTests.cs index f5a53a54..fb250eda 100644 --- a/src/LightInject.Tests/ServiceRegistrationTests.cs +++ b/src/LightInject.Tests/ServiceRegistrationTests.cs @@ -3,6 +3,8 @@ namespace LightInject.Tests using System; using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; using SampleLibrary; using Xunit; @@ -85,6 +87,57 @@ public void GetInstance_OverrideImplementingType_CreateInstanceOfOverriddenImple Assert.IsAssignableFrom(instance); } + [Fact] + public void GetInstance_OverrideLifeTime_CallsFactoryOnlyOnce() + { + var container = new ServiceContainer(); + + container.Register(); + container.Register(); + container.RegisterSingleton(); + + container.Override(sr => sr.ServiceType == typeof(C), (f, r) => + { + r.Lifetime = new PerContainerLifetime(); + return r; + }); + + var a = container.GetInstance(); + Assert.Same(a.C, a.B.C); + } + + public class A + { + public A(B b, C c) + { + B = b; + C = c; + } + + public B B { get; } + public C C { get; } + } + + public class B + { + public B(C c) + { + C = c; + } + + public C C { get; } + } + + + public class C + { + public C() + { + Thread.Sleep(100); + } + } + + [Fact] public void ToString_WithAllProperties_ReturnsEasyToReadRepresentation() { diff --git a/src/LightInject/LightInject.cs b/src/LightInject/LightInject.cs index 3bab4da2..19a40233 100644 --- a/src/LightInject/LightInject.cs +++ b/src/LightInject/LightInject.cs @@ -2956,11 +2956,7 @@ public IServiceRegistry Decorate(DecoratorRegistration decoratorRegistration) /// public IServiceRegistry Override(Func serviceSelector, Func serviceRegistrationFactory) { - var serviceOverride = new ServiceOverride - { - CanOverride = serviceSelector, - ServiceRegistrationFactory = serviceRegistrationFactory, - }; + var serviceOverride = new ServiceOverride(serviceSelector, serviceRegistrationFactory); overrides.Add(serviceOverride); return this; } @@ -4649,7 +4645,7 @@ private Action ResolveEmitMethod(ServiceRegistration serviceRegistrati var serviceOverrides = overrides.Items.Where(so => so.CanOverride(serviceRegistration)).ToArray(); foreach (var serviceOverride in serviceOverrides) { - serviceRegistration = serviceOverride.ServiceRegistrationFactory(this, serviceRegistration); + serviceRegistration = serviceOverride.Execute(this, serviceRegistration); } if (serviceRegistration.Lifetime == null) @@ -5014,9 +5010,45 @@ private class Initializer private class ServiceOverride { - public Func CanOverride { get; set; } + private readonly object lockObject = new object(); - public Func ServiceRegistrationFactory { get; set; } + private readonly Func serviceRegistrationFactory; + + private bool hasExecuted; + + public ServiceOverride(Func canOverride, Func serviceRegistrationFactory) + { + CanOverride = canOverride; + this.serviceRegistrationFactory = serviceRegistrationFactory; + } + + public Func CanOverride { get; } + + [ExcludeFromCodeCoverage] + public ServiceRegistration Execute(IServiceFactory serviceFactory, ServiceRegistration serviceRegistration) + { + // Excluded since the double checked lock is virtually impossible to produce. + if (hasExecuted) + { + return serviceRegistration; + } + else + { + lock (lockObject) + { + if (hasExecuted) + { + return serviceRegistration; + } + else + { + hasExecuted = true; + var registration = serviceRegistrationFactory(serviceFactory, serviceRegistration); + return registration; + } + } + } + } } } diff --git a/src/LightInject/LightInject.csproj b/src/LightInject/LightInject.csproj index 44c63e43..2ae5639b 100644 --- a/src/LightInject/LightInject.csproj +++ b/src/LightInject/LightInject.csproj @@ -2,7 +2,7 @@ netcoreapp2.0;netstandard2.0;netstandard1.6;netstandard1.3;netstandard1.1;net46;net452 - 6.3.5 + 6.3.6 Bernhard Richter https://www.lightinject.net git