diff --git a/src/Autofac/Builder/MetadataKeys.cs b/src/Autofac/Builder/MetadataKeys.cs index 8e068b9a0..1465a7f91 100644 --- a/src/Autofac/Builder/MetadataKeys.cs +++ b/src/Autofac/Builder/MetadataKeys.cs @@ -34,5 +34,7 @@ internal static class MetadataKeys internal const string StartOnActivatePropertyKey = "__StartOnActivate"; internal const string ContainerBuildOptions = "__ContainerBuildOptions"; + + internal const string RegisteredPropertyKey = "__RegisteredKey"; } } diff --git a/src/Autofac/Core/Registration/ComponentRegistry.cs b/src/Autofac/Core/Registration/ComponentRegistry.cs index 4cf9ebd8d..f4ba4fa2e 100644 --- a/src/Autofac/Core/Registration/ComponentRegistry.cs +++ b/src/Autofac/Core/Registration/ComponentRegistry.cs @@ -207,8 +207,7 @@ protected virtual void AddRegistration(IComponentRegistration registration, bool _registrations.Add(registration); - var handler = Registered; - handler?.Invoke(this, new ComponentRegisteredEventArgs(this, registration)); + GetRegistered()?.Invoke(this, new ComponentRegisteredEventArgs(this, registration)); } /// @@ -266,7 +265,24 @@ public IEnumerable DecoratorsFor(IComponentRegistration /// Fired whenever a component is registered - either explicitly or via a /// . /// - public event EventHandler Registered; + public event EventHandler Registered + { + add + { + lock (_synchRoot) + { + Properties[MetadataKeys.RegisteredPropertyKey] = GetRegistered() + value; + } + } + + remove + { + lock (_synchRoot) + { + Properties[MetadataKeys.RegisteredPropertyKey] = GetRegistered() - value; + } + } + } /// /// Add a registration source that will provide registrations on-the-fly. @@ -360,5 +376,13 @@ private ServiceRegistrationInfo GetServiceInfo(Service service) _serviceInfo.Add(service, info); return info; } + + private EventHandler GetRegistered() + { + if (Properties.TryGetValue(MetadataKeys.RegisteredPropertyKey, out var registered)) + return (EventHandler)registered; + + return null; + } } -} +} \ No newline at end of file diff --git a/test/Autofac.Test/ModuleTests.cs b/test/Autofac.Test/ModuleTests.cs index 3b25ae0cd..b3aad67e6 100644 --- a/test/Autofac.Test/ModuleTests.cs +++ b/test/Autofac.Test/ModuleTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Autofac.Builder; using Autofac.Core; using Autofac.Core.Registration; using Xunit; @@ -59,6 +60,70 @@ public void AttachesToRegistrations() Assert.Equal(container.ComponentRegistry.Registrations.Count(), attachingModule.Registrations.Count); } + [Fact] + public void AttachesToRegistrationsInScope() + { + var attachingModule = new AttachingModule(); + Assert.Equal(0, attachingModule.Registrations.Count); + + var builder = new ContainerBuilder(); + builder.RegisterModule(attachingModule); + + using (var container = builder.Build()) + using (var scope = container.BeginLifetimeScope(c => c.RegisterType(typeof(int)))) + { + var expected = container.ComponentRegistry.Registrations.Count() + scope.ComponentRegistry.Registrations.Count(); + Assert.Equal(expected, attachingModule.Registrations.Count); + } + } + + [Fact] + public void AttachesToRegistrationsInNestedScope() + { + var attachingModule = new AttachingModule(); + Assert.Equal(0, attachingModule.Registrations.Count); + + var builder = new ContainerBuilder(); + builder.RegisterModule(attachingModule); + + using (var container = builder.Build()) + using (var outerScope = container.BeginLifetimeScope(c => c.RegisterType(typeof(int)))) + using (var innerScope = outerScope.BeginLifetimeScope(c => c.RegisterType(typeof(double)))) + { + var expected = container.ComponentRegistry.Registrations.Count() + + outerScope.ComponentRegistry.Registrations.Count() + innerScope.ComponentRegistry.Registrations.Count(); + Assert.Equal(expected, attachingModule.Registrations.Count); + } + } + + [Fact] + public void ModifiedScopesHaveTheirOwnDelegate() + { + var attachingModule = new AttachingModule(); + Assert.Equal(0, attachingModule.Registrations.Count); + + var builder = new ContainerBuilder(); + builder.RegisterModule(attachingModule); + + using (var container = builder.Build()) + { + Assert.NotNull(container.ComponentRegistry.Properties[MetadataKeys.RegisteredPropertyKey]); + using (var outerScope = container.BeginLifetimeScope(c => c.RegisterType(typeof(int)))) + { + Assert.Equal( + container.ComponentRegistry.Properties[MetadataKeys.RegisteredPropertyKey], + outerScope.ComponentRegistry.Properties[MetadataKeys.RegisteredPropertyKey]); + outerScope.ComponentRegistry.Registered += (s, e) => { }; + using (var innerScope = outerScope.BeginLifetimeScope()) + { + Assert.NotEqual( + container.ComponentRegistry.Properties[MetadataKeys.RegisteredPropertyKey], + innerScope.ComponentRegistry.Properties[MetadataKeys.RegisteredPropertyKey]); + } + } + } + } + internal class ModuleExposingThisAssembly : Module { public Assembly ModuleThisAssembly