diff --git a/src/Autofac/Autofac.csproj b/src/Autofac/Autofac.csproj index a1d521c9c..1040687dd 100644 --- a/src/Autofac/Autofac.csproj +++ b/src/Autofac/Autofac.csproj @@ -4,7 +4,7 @@ Autofac is an IoC container for Microsoft .NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. 4.8.1 netstandard1.1;net45 - $(NoWarn);CS1591 + $(NoWarn);CS1591;CA1819 true true Autofac diff --git a/src/Autofac/Builder/ContainerBuildOptions.cs b/src/Autofac/Builder/ContainerBuildOptions.cs index 5db5df1d8..ae930c1f6 100644 --- a/src/Autofac/Builder/ContainerBuildOptions.cs +++ b/src/Autofac/Builder/ContainerBuildOptions.cs @@ -39,12 +39,6 @@ public enum ContainerBuildOptions /// None = 0, - /// - /// Prevents inclusion of standard modules like support for - /// relationship types including etc. - /// - ExcludeDefaultModules = 2, - /// /// Does not call on components implementing /// this interface (useful for module testing.) diff --git a/src/Autofac/Builder/IRegistrationBuilder.cs b/src/Autofac/Builder/IRegistrationBuilder.cs index 6734f4871..e1babdc36 100644 --- a/src/Autofac/Builder/IRegistrationBuilder.cs +++ b/src/Autofac/Builder/IRegistrationBuilder.cs @@ -278,5 +278,19 @@ public interface IRegistrationBuilder /// A registration builder allowing further configuration of the component. IRegistrationBuilder WithMetadata(Action> configurationAction); + + /// + /// Configure the services that the component will provide. + /// + /// Service types to expose. + /// A registration builder allowing further configuration of the component. + IRegistrationBuilder As(Type service); + + /// + /// Configure the services that the component will provide. + /// + /// Services to expose. + /// A registration builder allowing further configuration of the component. + IRegistrationBuilder As(Service service); } } diff --git a/src/Autofac/Builder/ReflectionActivatorData.cs b/src/Autofac/Builder/ReflectionActivatorData.cs index 0efbd539f..34e8e7224 100644 --- a/src/Autofac/Builder/ReflectionActivatorData.cs +++ b/src/Autofac/Builder/ReflectionActivatorData.cs @@ -108,11 +108,11 @@ public IConstructorSelector ConstructorSelector /// /// Gets the explicitly bound constructor parameters. /// - public IList ConfiguredParameters { get; } = new List(); + public List ConfiguredParameters { get; } = new List(); /// /// Gets the explicitly bound properties. /// - public IList ConfiguredProperties { get; } = new List(); + public List ConfiguredProperties { get; } = new List(); } } diff --git a/src/Autofac/Builder/RegistrationBuilder.cs b/src/Autofac/Builder/RegistrationBuilder.cs index 39e3129ee..e9ca8f67e 100644 --- a/src/Autofac/Builder/RegistrationBuilder.cs +++ b/src/Autofac/Builder/RegistrationBuilder.cs @@ -133,7 +133,7 @@ public static class RegistrationBuilder builder.RegistrationStyle.Id, builder.RegistrationData, builder.ActivatorData.Activator, - builder.RegistrationData.Services, + builder.RegistrationData.Services.ToArray(), builder.RegistrationStyle.Target); } @@ -149,7 +149,7 @@ public static class RegistrationBuilder Guid id, RegistrationData data, IInstanceActivator activator, - IEnumerable services) + Service[] services) { return CreateRegistration(id, data, activator, services, null); } @@ -170,7 +170,7 @@ public static class RegistrationBuilder Guid id, RegistrationData data, IInstanceActivator activator, - IEnumerable services, + Service[] services, IComponentRegistration target) { if (activator == null) throw new ArgumentNullException(nameof(activator)); @@ -179,11 +179,15 @@ public static class RegistrationBuilder var limitType = activator.LimitType; if (limitType != typeof(object)) { - foreach (var ts in services.OfType()) + foreach (var ts in services) { - if (!ts.ServiceType.GetTypeInfo().IsAssignableFrom(limitType.GetTypeInfo())) + var asServiceWithType = ts as IServiceWithType; + if (asServiceWithType != null) { - throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RegistrationBuilderResources.ComponentDoesNotSupportService, limitType, ts)); + if (!asServiceWithType.ServiceType.GetTypeInfo().IsAssignableFrom(limitType.GetTypeInfo())) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RegistrationBuilderResources.ComponentDoesNotSupportService, limitType, ts)); + } } } } diff --git a/src/Autofac/Builder/RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}.cs b/src/Autofac/Builder/RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}.cs index cf2ed5f15..22729e692 100644 --- a/src/Autofac/Builder/RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}.cs +++ b/src/Autofac/Builder/RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}.cs @@ -241,11 +241,27 @@ public RegistrationBuilder(Service defaultService, TActivatorData activatorData, /// A registration builder allowing further configuration of the component. public IRegistrationBuilder As(params Type[] services) { - return As(services.Select(t => - t.FullName != null - ? new TypedService(t) - : new TypedService(t.GetGenericTypeDefinition())) - .Cast().ToArray()); + Service[] argArray = new Service[services.Length]; + + for (int i = 0; i < services.Length; i++) + { + if (services[i].FullName != null) + argArray[i] = new TypedService(services[i]); + else + argArray[i] = new TypedService(services[i].GetGenericTypeDefinition()); + } + + return As(argArray); + } + + /// + /// Configure the services that the component will provide. + /// + /// Service types to expose. + /// A registration builder allowing further configuration of the component. + public IRegistrationBuilder As(Type service) + { + return As(new TypedService(service)); } /// @@ -262,6 +278,20 @@ public RegistrationBuilder(Service defaultService, TActivatorData activatorData, return this; } + /// + /// Configure the services that the component will provide. + /// + /// Services to expose. + /// A registration builder allowing further configuration of the component. + public IRegistrationBuilder As(Service service) + { + if (service == null) throw new ArgumentNullException(nameof(service)); + + RegistrationData.AddService(service); + + return this; + } + /// /// Provide a textual name that can be used to retrieve the component. /// diff --git a/src/Autofac/Builder/RegistrationData.cs b/src/Autofac/Builder/RegistrationData.cs index 5f1b8f2cb..ad0fd2a4e 100644 --- a/src/Autofac/Builder/RegistrationData.cs +++ b/src/Autofac/Builder/RegistrationData.cs @@ -41,7 +41,7 @@ public class RegistrationData private bool _defaultServiceOverridden; private Service _defaultService; - private readonly ICollection _services = new HashSet(); + private readonly HashSet _services = new HashSet(); private IComponentLifetime _lifetime = new CurrentScopeLifetime(); @@ -56,7 +56,7 @@ public RegistrationData(Service defaultService) _defaultService = defaultService; - Metadata = new Dictionary + Metadata = new Dictionary(1) { { MetadataKeys.RegistrationOrderMetadataKey, SequenceGenerator.GetNextUniqueSequence() }, }; @@ -147,17 +147,17 @@ public IComponentLifetime Lifetime /// /// Gets the handlers for the Preparing event. /// - public ICollection> PreparingHandlers { get; } = new List>(); + public List> PreparingHandlers { get; } = new List>(); /// /// Gets the handlers for the Activating event. /// - public ICollection>> ActivatingHandlers { get; } = new List>>(); + public List>> ActivatingHandlers { get; } = new List>>(); /// /// Gets the handlers for the Activated event. /// - public ICollection>> ActivatedHandlers { get; } = new List>>(); + public List>> ActivatedHandlers { get; } = new List>>(); /// /// Copies the contents of another RegistrationData object into this one. diff --git a/src/Autofac/Builder/SingleRegistrationStyle.cs b/src/Autofac/Builder/SingleRegistrationStyle.cs index 7bd3593a7..90df3f376 100644 --- a/src/Autofac/Builder/SingleRegistrationStyle.cs +++ b/src/Autofac/Builder/SingleRegistrationStyle.cs @@ -42,7 +42,7 @@ public class SingleRegistrationStyle /// /// Gets the handlers to notify of the component registration event. /// - public ICollection> RegisteredHandlers { get; } = new List>(); + public List> RegisteredHandlers { get; } = new List>(); /// /// Gets or sets a value indicating whether default registrations should be preserved. diff --git a/src/Autofac/ContainerBuilder.cs b/src/Autofac/ContainerBuilder.cs index 388dfbc80..8f0f5b81a 100644 --- a/src/Autofac/ContainerBuilder.cs +++ b/src/Autofac/ContainerBuilder.cs @@ -131,6 +131,7 @@ public ContainerBuilder RegisterBuildCallback(Action buildCallback) /// Create a new container with the component registrations that have been made. /// /// Options that influence the way the container is initialised. + /// Defines which default services should be enabled. /// /// Build can only be called once per /// - this prevents ownership issues for provided instances. @@ -139,11 +140,11 @@ public ContainerBuilder RegisterBuildCallback(Action buildCallback) /// first create the container, then call Update() on the builder. /// /// A new container with the configured component registrations. - public IContainer Build(ContainerBuildOptions options = ContainerBuildOptions.None) + public IContainer Build(ContainerBuildOptions options = ContainerBuildOptions.None, DefaultServiceFlags flags = DefaultServiceFlags.All) { var result = new Container(Properties); result.ComponentRegistry.Properties[MetadataKeys.ContainerBuildOptions] = options; - Build(result.ComponentRegistry, (options & ContainerBuildOptions.ExcludeDefaultModules) != ContainerBuildOptions.None); + Build(result.ComponentRegistry, flags); if ((options & ContainerBuildOptions.IgnoreStartableComponents) == ContainerBuildOptions.None) StartableManager.StartStartableComponents(result); @@ -206,7 +207,7 @@ public void Update(IContainer container, ContainerBuildOptions options) [Obsolete("Containers should generally be considered immutable. Register all of your dependencies before building/resolving. If you need to change the contents of a container, you technically should rebuild the container. This method may be removed in a future major release.")] public void Update(IComponentRegistry componentRegistry) { - this.UpdateRegistry(componentRegistry); + UpdateRegistry(componentRegistry); } /// @@ -222,10 +223,10 @@ public void Update(IComponentRegistry componentRegistry) internal void UpdateRegistry(IComponentRegistry componentRegistry) { if (componentRegistry == null) throw new ArgumentNullException(nameof(componentRegistry)); - Build(componentRegistry, true); + Build(componentRegistry, DefaultServiceFlags.None); } - private void Build(IComponentRegistry componentRegistry, bool excludeDefaultModules) + private void Build(IComponentRegistry componentRegistry, DefaultServiceFlags flags = DefaultServiceFlags.None) { if (componentRegistry == null) throw new ArgumentNullException(nameof(componentRegistry)); @@ -234,23 +235,30 @@ private void Build(IComponentRegistry componentRegistry, bool excludeDefaultModu _wasBuilt = true; - if (!excludeDefaultModules) - RegisterDefaultAdapters(componentRegistry); + RegisterDefaultAdapters(componentRegistry, flags); foreach (var callback in _configurationCallbacks) callback.Callback(componentRegistry); } - private void RegisterDefaultAdapters(IComponentRegistry componentRegistry) + private void RegisterDefaultAdapters(IComponentRegistry componentRegistry, DefaultServiceFlags flags) { - this.RegisterGeneric(typeof(KeyedServiceIndex<,>)).As(typeof(IIndex<,>)).InstancePerLifetimeScope(); - componentRegistry.AddRegistrationSource(new CollectionRegistrationSource()); - componentRegistry.AddRegistrationSource(new OwnedInstanceRegistrationSource()); - componentRegistry.AddRegistrationSource(new MetaRegistrationSource()); - componentRegistry.AddRegistrationSource(new LazyRegistrationSource()); - componentRegistry.AddRegistrationSource(new LazyWithMetadataRegistrationSource()); - componentRegistry.AddRegistrationSource(new StronglyTypedMetaRegistrationSource()); - componentRegistry.AddRegistrationSource(new GeneratedFactoryRegistrationSource()); + if ((flags & DefaultServiceFlags.Index) == DefaultServiceFlags.Index) + this.RegisterGeneric(typeof(KeyedServiceIndex<,>)).As(new[] { typeof(IIndex<,>) }).InstancePerLifetimeScope(); + if ((flags & DefaultServiceFlags.Collections) == DefaultServiceFlags.Collections) + componentRegistry.AddRegistrationSource(new CollectionRegistrationSource()); + if ((flags & DefaultServiceFlags.Owned) == DefaultServiceFlags.Owned) + componentRegistry.AddRegistrationSource(new OwnedInstanceRegistrationSource()); + if ((flags & DefaultServiceFlags.Meta) == DefaultServiceFlags.Meta) + componentRegistry.AddRegistrationSource(new MetaRegistrationSource()); + if ((flags & DefaultServiceFlags.Lazy) == DefaultServiceFlags.Lazy) + componentRegistry.AddRegistrationSource(new LazyRegistrationSource()); + if ((flags & DefaultServiceFlags.LazyWithMeta) == DefaultServiceFlags.LazyWithMeta) + componentRegistry.AddRegistrationSource(new LazyWithMetadataRegistrationSource()); + if ((flags & DefaultServiceFlags.StronglyTypedMeta) == DefaultServiceFlags.StronglyTypedMeta) + componentRegistry.AddRegistrationSource(new StronglyTypedMetaRegistrationSource()); + if ((flags & DefaultServiceFlags.GeneratedFactory) == DefaultServiceFlags.GeneratedFactory) + componentRegistry.AddRegistrationSource(new GeneratedFactoryRegistrationSource()); } private List> GetBuildCallbacks() @@ -258,4 +266,58 @@ private List> GetBuildCallbacks() return (List>)Properties[BuildCallbackPropertyKey]; } } + + [Flags] + public enum DefaultServiceFlags + { + /// + /// None + /// + None = 0, + + /// + /// Index + /// + Index = 1, + + /// + /// Collection + /// + Collections = 2, + + /// + /// Owned + /// + Owned = 4, + + /// + /// Meta + /// + Meta = 8, + + /// + /// Lazy + /// + Lazy = 16, + + /// + /// LazyWithMeta + /// + LazyWithMeta = 32, + + /// + /// StronglyTypedMeta + /// + StronglyTypedMeta = 64, + + /// + /// GeneratedFactory + /// + GeneratedFactory = 128, + + /// + /// All + /// + All = Index | Collections | Owned | Meta | Lazy | LazyWithMeta | StronglyTypedMeta | GeneratedFactory + } } \ No newline at end of file diff --git a/src/Autofac/Core/Activators/Reflection/ConstructorParameterBinding.cs b/src/Autofac/Core/Activators/Reflection/ConstructorParameterBinding.cs index 92c052b20..98de71e10 100644 --- a/src/Autofac/Core/Activators/Reflection/ConstructorParameterBinding.cs +++ b/src/Autofac/Core/Activators/Reflection/ConstructorParameterBinding.cs @@ -66,7 +66,7 @@ public class ConstructorParameterBinding /// Context in which to construct instance. public ConstructorParameterBinding( ConstructorInfo ci, - IEnumerable availableParameters, + Parameter[] availableParameters, IComponentContext context) { if (ci == null) throw new ArgumentNullException(nameof(ci)); diff --git a/src/Autofac/Core/Activators/Reflection/ReflectionActivator.cs b/src/Autofac/Core/Activators/Reflection/ReflectionActivator.cs index d97efaff7..d9f24c3be 100644 --- a/src/Autofac/Core/Activators/Reflection/ReflectionActivator.cs +++ b/src/Autofac/Core/Activators/Reflection/ReflectionActivator.cs @@ -57,8 +57,8 @@ public class ReflectionActivator : InstanceActivator, IInstanceActivator Type implementationType, IConstructorFinder constructorFinder, IConstructorSelector constructorSelector, - IEnumerable configuredParameters, - IEnumerable configuredProperties) + IList configuredParameters, + IList configuredProperties) : base(implementationType) { if (constructorFinder == null) throw new ArgumentNullException(nameof(constructorFinder)); @@ -70,7 +70,14 @@ public class ReflectionActivator : InstanceActivator, IInstanceActivator ConstructorFinder = constructorFinder; ConstructorSelector = constructorSelector; _configuredProperties = configuredProperties.ToArray(); - _defaultParameters = configuredParameters.Concat(new Parameter[] { new AutowiringParameter(), new DefaultValueParameter() }).ToArray(); + + _defaultParameters = new Parameter[configuredParameters.Count + 2]; + + for (int i = 0; i < configuredParameters.Count; i++) + _defaultParameters[i] = configuredParameters[i]; + + _defaultParameters[_defaultParameters.Length - 2] = new AutowiringParameter(); + _defaultParameters[_defaultParameters.Length - 1] = new DefaultValueParameter(); } /// @@ -128,10 +135,25 @@ public object ActivateInstance(IComponentContext context, IEnumerable private ConstructorParameterBinding[] GetValidConstructorBindings(IComponentContext context, IEnumerable parameters) { - // Most often, there will be no `parameters` and/or no `_defaultParameters`; in both of those cases we can avoid allocating. - var prioritisedParameters = parameters.Any() ? - (_defaultParameters.Length == 0 ? parameters : parameters.Concat(_defaultParameters)) : - _defaultParameters; + // Most often, there will be no `parameters`we can avoid allocating. + Parameter[] prioritisedParameters; + if (parameters is Parameter[] parametersArray) + { + if (parametersArray.Length == 0) + { + prioritisedParameters = _defaultParameters; + } + else + { + prioritisedParameters = new Parameter[_defaultParameters.Length + parametersArray.Length]; + Array.Copy(parametersArray, 0, prioritisedParameters, 0, parametersArray.Length); + Array.Copy(_defaultParameters, 0, prioritisedParameters, parametersArray.Length, _defaultParameters.Length); + } + } + else + { + prioritisedParameters = parameters.Concat(_defaultParameters).ToArray(); + } var constructorBindings = new ConstructorParameterBinding[_availableConstructors.Length]; for (var i = 0; i < _availableConstructors.Length; ++i) diff --git a/src/Autofac/Core/IComponentRegistration.cs b/src/Autofac/Core/IComponentRegistration.cs index 763db0e76..fb00d83af 100644 --- a/src/Autofac/Core/IComponentRegistration.cs +++ b/src/Autofac/Core/IComponentRegistration.cs @@ -63,7 +63,7 @@ public interface IComponentRegistration : IDisposable /// /// Gets the services provided by the component. /// - IEnumerable Services { get; } + Service[] Services { get; } /// /// Gets additional data associated with the component. diff --git a/src/Autofac/Core/Registration/ComponentRegistration.cs b/src/Autofac/Core/Registration/ComponentRegistration.cs index 8df7e41d4..cc908198c 100644 --- a/src/Autofac/Core/Registration/ComponentRegistration.cs +++ b/src/Autofac/Core/Registration/ComponentRegistration.cs @@ -56,20 +56,21 @@ public class ComponentRegistration : Disposable, IComponentRegistration IComponentLifetime lifetime, InstanceSharing sharing, InstanceOwnership ownership, - IEnumerable services, + Service[] services, IDictionary metadata) { if (activator == null) throw new ArgumentNullException(nameof(activator)); if (lifetime == null) throw new ArgumentNullException(nameof(lifetime)); if (services == null) throw new ArgumentNullException(nameof(services)); if (metadata == null) throw new ArgumentNullException(nameof(metadata)); + Enforce.ArgumentElementNotNull(services, nameof(services)); Id = id; Activator = activator; Lifetime = lifetime; Sharing = sharing; Ownership = ownership; - Services = Enforce.ArgumentElementNotNull(services, nameof(services)); + Services = services; Metadata = metadata; } @@ -90,7 +91,7 @@ public class ComponentRegistration : Disposable, IComponentRegistration IComponentLifetime lifetime, InstanceSharing sharing, InstanceOwnership ownership, - IEnumerable services, + Service[] services, IDictionary metadata, IComponentRegistration target) : this(id, activator, lifetime, sharing, ownership, services, metadata) @@ -135,7 +136,7 @@ public class ComponentRegistration : Disposable, IComponentRegistration /// /// Gets the services provided by the component. /// - public IEnumerable Services { get; } + public Service[] Services { get; } /// /// Gets additional data associated with the component. diff --git a/src/Autofac/Core/Registration/ComponentRegistrationLifetimeDecorator.cs b/src/Autofac/Core/Registration/ComponentRegistrationLifetimeDecorator.cs index bd9b2cb50..0632135f4 100644 --- a/src/Autofac/Core/Registration/ComponentRegistrationLifetimeDecorator.cs +++ b/src/Autofac/Core/Registration/ComponentRegistrationLifetimeDecorator.cs @@ -54,7 +54,7 @@ public ComponentRegistrationLifetimeDecorator(IComponentRegistration inner, ICom public InstanceOwnership Ownership => _inner.Ownership; - public IEnumerable Services => _inner.Services; + public Service[] Services => _inner.Services; public IDictionary Metadata => _inner.Metadata; diff --git a/src/Autofac/Core/Registration/ComponentRegistry.cs b/src/Autofac/Core/Registration/ComponentRegistry.cs index 4baf220c9..1148517a2 100644 --- a/src/Autofac/Core/Registration/ComponentRegistry.cs +++ b/src/Autofac/Core/Registration/ComponentRegistry.cs @@ -52,17 +52,17 @@ public class ComponentRegistry : Disposable, IComponentRegistry /// /// External registration sources. /// - private readonly IList _dynamicRegistrationSources = new List(); + private readonly List _dynamicRegistrationSources = new List(); /// /// All registrations. /// - private readonly ICollection _registrations = new List(); + private readonly List _registrations = new List(); /// /// Keeps track of the status of registered services. /// - private readonly IDictionary _serviceInfo = new Dictionary(); + private readonly Dictionary _serviceInfo = new Dictionary(); /// /// Initializes a new instance of the class. @@ -162,12 +162,17 @@ public void Register(IComponentRegistration registration, bool preserveDefaults) private void UpdateInitialisedAdapters(IComponentRegistration registration) { - var adapterServices = _serviceInfo - .Where(si => si.Value.ShouldRecalculateAdaptersOn(registration)) - .Select(si => si.Key) - .ToArray(); + List adapterServices = new List(); - if (adapterServices.Length == 0) + foreach (var serviceInfo in _serviceInfo) + { + if (serviceInfo.Value.ShouldRecalculateAdaptersOn(registration)) + { + adapterServices.Add(serviceInfo.Key); + } + } + + if (adapterServices.Count == 0) return; Debug.WriteLine( diff --git a/src/Autofac/Core/Registration/ExternalRegistrySource.cs b/src/Autofac/Core/Registration/ExternalRegistrySource.cs index 6543aa737..53da9af39 100644 --- a/src/Autofac/Core/Registration/ExternalRegistrySource.cs +++ b/src/Autofac/Core/Registration/ExternalRegistrySource.cs @@ -105,7 +105,7 @@ public IEnumerable RegistrationsFor(Service service, Fun /// private class ExternalComponentRegistration : ComponentRegistration { - public ExternalComponentRegistration(Guid id, IInstanceActivator activator, IComponentLifetime lifetime, InstanceSharing sharing, InstanceOwnership ownership, IEnumerable services, IDictionary metadata, IComponentRegistration target) + public ExternalComponentRegistration(Guid id, IInstanceActivator activator, IComponentLifetime lifetime, InstanceSharing sharing, InstanceOwnership ownership, Service[] services, IDictionary metadata, IComponentRegistration target) : base(id, activator, lifetime, sharing, ownership, services, metadata, target) { } diff --git a/src/Autofac/Core/Registration/ServiceRegistrationInfo.cs b/src/Autofac/Core/Registration/ServiceRegistrationInfo.cs index 7688ee77f..f4af257a9 100644 --- a/src/Autofac/Core/Registration/ServiceRegistrationInfo.cs +++ b/src/Autofac/Core/Registration/ServiceRegistrationInfo.cs @@ -48,13 +48,13 @@ internal class ServiceRegistrationInfo /// List of service implementations coming from sources. Sources have priority over preserve-default implementations. /// Implementations from sources are enumerated in preserve-default order, so the most default implementation comes first. /// - private readonly List _sourceImplementations = new List(); + private List _sourceImplementations; /// /// List of explicit service implementations specified with the PreserveExistingDefaults option. /// Enumerated in preserve-defaults order, so the most default implementation comes first. /// - private readonly List _preserveDefaultImplementations = new List(); + private List _preserveDefaultImplementations; [SuppressMessage("Microsoft.ApiDesignGuidelines", "CA2213", Justification = "The creator of the compponent registration is responsible for disposal.")] private IComponentRegistration _defaultImplementation; @@ -88,10 +88,16 @@ public IEnumerable Implementations get { RequiresInitialization(); - return Enumerable - .Reverse(_defaultImplementations) - .Concat(_sourceImplementations) - .Concat(_preserveDefaultImplementations); + + var resultingCollection = Enumerable.Reverse(_defaultImplementations); + + if (_sourceImplementations != null) + resultingCollection = resultingCollection.Concat(_sourceImplementations); + + if (_preserveDefaultImplementations != null) + resultingCollection = resultingCollection.Concat(_preserveDefaultImplementations); + + return resultingCollection; } } @@ -114,18 +120,28 @@ public bool IsRegistered } private bool Any => - _defaultImplementations.Any() || - _sourceImplementations.Any() || - _preserveDefaultImplementations.Any(); + _defaultImplementations.Count > 0 || + _sourceImplementations != null || + _preserveDefaultImplementations != null; public void AddImplementation(IComponentRegistration registration, bool preserveDefaults, bool originatedFromSource) { if (preserveDefaults) { if (originatedFromSource) + { + if (_sourceImplementations == null) + _sourceImplementations = new List(); + _sourceImplementations.Add(registration); + } else + { + if (_preserveDefaultImplementations == null) + _preserveDefaultImplementations = new List(); + _preserveDefaultImplementations.Add(registration); + } } else { @@ -144,8 +160,8 @@ public bool TryGetRegistration(out IComponentRegistration registration) registration = _defaultImplementation ?? (_defaultImplementation = _defaultImplementations.LastOrDefault() ?? - _sourceImplementations.FirstOrDefault() ?? - _preserveDefaultImplementations.FirstOrDefault()); + _sourceImplementations?.First() ?? + _preserveDefaultImplementations?.First()); return registration != null; } @@ -214,7 +230,9 @@ public bool ShouldRecalculateAdaptersOn(IComponentRegistration registration) // - Have already been initialized // - Were created via a registration source (because we might be adding an equivalent explicit registration such as Func) // - Don't contain any registrations (because a registration source was added when no adaptee was present) - return IsInitialized && (_sourceImplementations.Any() || !Any); + bool result = IsInitialized && (_sourceImplementations != null || !Any); + + return result; } } } \ No newline at end of file diff --git a/src/Autofac/Core/Resolving/CircularDependencyDetector.cs b/src/Autofac/Core/Resolving/CircularDependencyDetector.cs index b5980c818..d751a39a4 100644 --- a/src/Autofac/Core/Resolving/CircularDependencyDetector.cs +++ b/src/Autofac/Core/Resolving/CircularDependencyDetector.cs @@ -61,8 +61,11 @@ public static void CheckForCircularDependency(IComponentRegistration registratio throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, CircularDependencyDetectorResources.MaxDepthExceeded, registration)); // Checks for circular dependency - if (activationStack.Any(a => a.ComponentRegistration == registration)) - throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, CircularDependencyDetectorResources.CircularDependency, CreateDependencyGraphTo(registration, activationStack))); + foreach (var a in activationStack) + { + if (a.ComponentRegistration == registration) + throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, CircularDependencyDetectorResources.CircularDependency, CreateDependencyGraphTo(registration, activationStack))); + } } } } diff --git a/src/Autofac/Features/OpenGenerics/OpenGenericDecoratorRegistrationSource.cs b/src/Autofac/Features/OpenGenerics/OpenGenericDecoratorRegistrationSource.cs index 094e8702b..8198dddd4 100644 --- a/src/Autofac/Features/OpenGenerics/OpenGenericDecoratorRegistrationSource.cs +++ b/src/Autofac/Features/OpenGenerics/OpenGenericDecoratorRegistrationSource.cs @@ -60,7 +60,7 @@ public IEnumerable RegistrationsFor(Service service, Fun if (registrationAccessor == null) throw new ArgumentNullException(nameof(registrationAccessor)); Type constructedImplementationType; - IEnumerable services; + Service[] services; if (OpenGenericServiceBinder.TryBindServiceType(service, _registrationData.Services, _activatorData.ImplementationType, out constructedImplementationType, out services)) { var swt = (IServiceWithType)service; @@ -77,13 +77,19 @@ public IEnumerable RegistrationsFor(Service service, Fun return Enumerable.Empty(); } - private static IEnumerable AddDecoratedComponentParameter(Type decoratedParameterType, IComponentRegistration decoratedComponent, IEnumerable configuredParameters) + private static IList AddDecoratedComponentParameter(Type decoratedParameterType, IComponentRegistration decoratedComponent, IList configuredParameters) { var parameter = new ResolvedParameter( (pi, c) => pi.ParameterType == decoratedParameterType, (pi, c) => c.ResolveComponent(decoratedComponent, Enumerable.Empty())); - return new[] { parameter }.Concat(configuredParameters); + var resultArray = new Parameter[configuredParameters.Count + 1]; + resultArray[0] = parameter; + + for (int i = 0; i < configuredParameters.Count; i++) + resultArray[i + 1] = configuredParameters[i]; + + return resultArray; } public bool IsAdapterForIndividualComponents => true; diff --git a/src/Autofac/Features/OpenGenerics/OpenGenericRegistrationSource.cs b/src/Autofac/Features/OpenGenerics/OpenGenericRegistrationSource.cs index 92cd9302e..3447fc478 100644 --- a/src/Autofac/Features/OpenGenerics/OpenGenericRegistrationSource.cs +++ b/src/Autofac/Features/OpenGenerics/OpenGenericRegistrationSource.cs @@ -60,7 +60,7 @@ public IEnumerable RegistrationsFor(Service service, Fun if (registrationAccessor == null) throw new ArgumentNullException(nameof(registrationAccessor)); Type constructedImplementationType; - IEnumerable services; + Service[] services; if (OpenGenericServiceBinder.TryBindServiceType(service, _registrationData.Services, _activatorData.ImplementationType, out constructedImplementationType, out services)) { yield return RegistrationBuilder.CreateRegistration( diff --git a/src/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs b/src/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs index 93b4ec1ac..4d96f61b9 100644 --- a/src/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs +++ b/src/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs @@ -41,7 +41,7 @@ internal static class OpenGenericServiceBinder IEnumerable configuredOpenGenericServices, Type openGenericImplementationType, out Type constructedImplementationType, - out IEnumerable constructedServices) + out Service[] constructedServices) { var swt = service as IServiceWithType; if (swt != null && swt.ServiceType.GetTypeInfo().IsGenericType) diff --git a/src/Autofac/ModuleRegistrationExtensions.cs b/src/Autofac/ModuleRegistrationExtensions.cs index d2e2b0ecd..7808ee023 100644 --- a/src/Autofac/ModuleRegistrationExtensions.cs +++ b/src/Autofac/ModuleRegistrationExtensions.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using Autofac.Builder; using Autofac.Core; using Autofac.Core.Registration; @@ -164,7 +165,7 @@ public static IModuleRegistrar RegisterAssemblyModules(this IModuleRegistrar reg .Where(t => moduleType.GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())) .As(); - using (var moduleContainer = moduleFinder.Build()) + using (var moduleContainer = moduleFinder.Build(ContainerBuildOptions.None)) { foreach (var module in moduleContainer.Resolve>()) { diff --git a/test/Autofac.Test/ContainerBuilderTests.cs b/test/Autofac.Test/ContainerBuilderTests.cs index ca4de293e..3b4499e42 100644 --- a/test/Autofac.Test/ContainerBuilderTests.cs +++ b/test/Autofac.Test/ContainerBuilderTests.cs @@ -369,7 +369,7 @@ public void WhenUpdating_DefaultModulesAreExcluded() public void WhenBuildingWithDefaultsExcluded_DefaultModulesAreExcluded() { var builder = new ContainerBuilder(); - var container = builder.Build(ContainerBuildOptions.ExcludeDefaultModules); + var container = builder.Build(ContainerBuildOptions.None, DefaultServiceFlags.None); Assert.False(container.IsRegistered>()); } diff --git a/test/Autofac.Test/Factory.cs b/test/Autofac.Test/Factory.cs index 53a2be374..004541762 100644 --- a/test/Autofac.Test/Factory.cs +++ b/test/Autofac.Test/Factory.cs @@ -33,7 +33,7 @@ public static IComponentRegistration CreateRegistration(IEnumerable ser lifetime, sharing, InstanceOwnership.OwnedByLifetimeScope, - services, + services.ToArray(), GetDefaultMetadata()); } @@ -78,8 +78,8 @@ public static ReflectionActivator CreateReflectionActivator(Type implementation, implementation, new DefaultConstructorFinder(), new MostParametersConstructorSelector(), - parameters, - properties); + parameters.ToArray(), + properties.ToArray()); } public static ProvidedInstanceActivator CreateProvidedInstanceActivator(object instance) @@ -99,8 +99,8 @@ public static ProvidedInstanceActivator CreateProvidedInstanceActivator(object i public static readonly IComponentContext EmptyContext = new Container(); - public static readonly IEnumerable NoParameters = Enumerable.Empty(); + public static readonly Parameter[] NoParameters = new Parameter[0]; - public static readonly IEnumerable NoProperties = Enumerable.Empty(); + public static readonly Parameter[] NoProperties = new Parameter[0]; } } diff --git a/test/Autofac.Test/Mocks.cs b/test/Autofac.Test/Mocks.cs index 2cf9b18b7..4f551c018 100644 --- a/test/Autofac.Test/Mocks.cs +++ b/test/Autofac.Test/Mocks.cs @@ -73,7 +73,7 @@ public void Dispose() public InstanceOwnership Ownership { get; } - public IEnumerable Services { get; } = new Service[0]; + public Service[] Services { get; } = new Service[0]; public IDictionary Metadata { get; }