private static void AddAutoCrossWiring(
            Container container, IServiceProvider provider, SimpleInjectorAddOptions builder)
        {
            var scopeFactory = provider.GetRequiredService <IServiceScopeFactory>();
            var services     = builder.Services;

            container.ResolveUnregisteredType += (s, e) =>
            {
                if (e.Handled)
                {
                    return;
                }

                Type serviceType = e.UnregisteredServiceType;

                ServiceDescriptor descriptor = FindServiceDescriptor(services, serviceType);

                if (descriptor != null)
                {
                    Registration registration =
                        CreateCrossWireRegistration(
                            builder,
                            provider,
                            serviceType,
                            ToLifestyle(descriptor.Lifetime));

                    e.Register(registration);
                }
            };
        }
        /// <summary>
        /// Sets up the basic configuration that allows Simple Injector to be used in frameworks that require
        /// the use of <see cref="IServiceCollection"/> for registration of framework components.
        /// In case of the absense of a
        /// <see cref="ContainerOptions.DefaultScopedLifestyle">DefaultScopedLifestyle</see>, this method
        /// will configure <see cref="AsyncScopedLifestyle"/> as the default scoped lifestyle.
        /// In case a <paramref name="setupAction"/> is supplied, that delegate will be called that allow
        /// further configuring the container.
        /// </summary>
        /// <param name="services">The framework's <see cref="IServiceCollection"/> instance.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <param name="setupAction">An optional setup action.</param>
        /// <returns>The supplied <paramref name="services"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="services"/> or
        /// <paramref name="container"/> are null references.</exception>
        public static IServiceCollection AddSimpleInjector(
            this IServiceCollection services,
            Container container,
            Action <SimpleInjectorAddOptions> setupAction = null)
        {
            if (services is null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            var options = new SimpleInjectorAddOptions(
                services,
                container,
                new DefaultServiceProviderAccessor(container));

            // This stores the options, which includes the IServiceCollection. IServiceCollection is required
            // when calling UseSimpleInjector to enable auto cross wiring.
            AddSimpleInjectorOptions(container, options);

            // Set lifestyle before calling setupAction. Code in the delegate might depend on that.
            TrySetDefaultScopedLifestyle(container);

            setupAction?.Invoke(options);

            return(services);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Allows components that are built by Simple Injector to depend on the (non-generic)
        /// <see cref="ILogger">Microsoft.Extensions.Logging.ILogger</see> abstraction. Components are
        /// injected with an contextual implementation. Using this method, application components can simply
        /// depend on <b>ILogger</b> instead of its generic counter part, <b>ILogger&lt;T&gt;</b>, which
        /// simplifies development.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>The supplied <paramref name="options"/>.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when <paramref name="options"/> is a null reference.</exception>
        /// <exception cref="InvalidOperationException">Thrown when no <see cref="ILoggerFactory"/> entry
        /// can be found in the framework's list of services defined by <see cref="IServiceCollection"/>.
        /// </exception>
        public static SimpleInjectorAddOptions AddLogging(this SimpleInjectorAddOptions options)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            EnsureMethodOnlyCalledOnce(options, nameof(AddLogging), AddLoggingKey);

            // Both RootLogger and Logger<T> depend on ILoggerFactory
            VerifyLoggerFactoryAvailable(options.Services);

            // Cross-wire ILoggerFactory explicitly, because auto cross-wiring might be disabled by the user.
            options.Container.RegisterSingleton(() => options.GetRequiredFrameworkService <ILoggerFactory>());

            Type genericLoggerType = GetGenericLoggerType();

            options.Container.RegisterConditional(
                typeof(ILogger),
                c => c.Consumer is null
                    ? typeof(RootLogger)
                    : genericLoggerType.MakeGenericType(c.Consumer.ImplementationType),
                Lifestyle.Singleton,
                _ => true);

            return(options);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Cross wires an ASP.NET Core or third-party service to the container, to allow the service to be
        /// injected into components that are built by Simple Injector.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="serviceType">The type of service object to ross-wire.</param>
        /// <returns>The supplied <paramref name="options"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when one of the parameters is a null reference.
        /// </exception>
        public static SimpleInjectorAddOptions CrossWire(
            this SimpleInjectorAddOptions options, Type serviceType)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (serviceType is null)
            {
                throw new ArgumentNullException(nameof(serviceType));
            }

            // At this point there is no IServiceProvider (ApplicationServices) yet, which is why we need to
            // postpone the registration of the cross-wired service. When the container gets locked, we will
            // (hopefully) have the IServiceProvider available.
            options.Container.Options.ContainerLocking += (s, e) =>
            {
                Registration registration = CreateCrossWireRegistration(
                    options,
                    options.ApplicationServices,
                    serviceType,
                    DetermineLifestyle(serviceType, options.Services));

                options.Container.AddRegistration(serviceType, registration);
            };

            return(options);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Allows components that are built by Simple Injector to depend on the (non-generic)
        /// <see cref="IStringLocalizer">Microsoft.Extensions.Localization.IStringLocalizer</see> abstraction.
        /// Components are injected with an contextual implementation. Using this method, application
        /// components can simply depend on <b>IStringLocalizer</b> instead of its generic counter part,
        /// <b>IStringLocalizer&lt;T&gt;</b>, which simplifies development.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>The supplied <paramref name="options"/>.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when <paramref name="options"/> is a null reference.</exception>
        /// <exception cref="InvalidOperationException">Thrown when no <see cref="IStringLocalizerFactory"/>
        /// entry can be found in the framework's list of services defined by <see cref="IServiceCollection"/>.
        /// </exception>
        /// <exception cref="ActivationException">Thrown when an <see cref="IStringLocalizer"/> is directly
        /// resolved from the container. Instead use <see cref="IStringLocalizer"/> within a constructor
        /// dependency.</exception>
        public static SimpleInjectorAddOptions AddLocalization(this SimpleInjectorAddOptions options)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            EnsureMethodOnlyCalledOnce(options, nameof(AddLocalization), AddLocalizationKey);

            VerifyStringLocalizerFactoryAvailable(options.Services);

            // Cross-wire IStringLocalizerFactory explicitly, because auto cross-wiring might be disabled.
            options.Container.RegisterSingleton(
                () => options.GetRequiredFrameworkService <IStringLocalizerFactory>());

            Type genericLocalizerType = GetGenericLocalizerType();

            options.Container.RegisterConditional(
                typeof(IStringLocalizer),
                c => c.Consumer is null
                    ? throw new ActivationException(
                    "IStringLocalizer is being resolved directly from the container, but this is not " +
                    "supported as string localizers need to be related to a consuming type. Instead, " +
                    "make IStringLocalizer a constructor dependency of the type it is used in.")
                    : genericLocalizerType.MakeGenericType(c.Consumer.ImplementationType),
                Lifestyle.Singleton,
                _ => true);

            return(options);
        }
Ejemplo n.º 6
0
        private static void AddAutoCrossWiring(SimpleInjectorAddOptions options)
        {
            // By using ContainerLocking, we ensure that this ResolveUnregisteredType registration is made
            // after all possible ResolveUnregisteredType registrations the users did themselves.
            options.Container.Options.ContainerLocking += (_, __) =>
            {
                // If there's no IServiceProvider, the property will throw, which is something we want to do
                // at this point, not later on, when an unregistered type is resolved.
                IServiceProvider provider = options.ApplicationServices;

                options.Container.ResolveUnregisteredType += (_, e) =>
                {
                    if (!e.Handled)
                    {
                        Type serviceType = e.UnregisteredServiceType;

                        ServiceDescriptor?descriptor = FindServiceDescriptor(options.Services, serviceType);

                        if (descriptor != null)
                        {
                            Registration registration =
                                CreateCrossWireRegistration(
                                    options,
                                    provider,
                                    serviceType,
                                    ToLifestyle(descriptor.Lifetime));

                            e.Register(registration);
                        }
                    }
                };
            };
        }
Ejemplo n.º 7
0
        private static Registration CreateCrossWireRegistration(
            SimpleInjectorAddOptions options,
            IServiceProvider provider,
            Type serviceType,
            Lifestyle lifestyle)
        {
            var registration = lifestyle.CreateRegistration(
                serviceType,
                lifestyle == Lifestyle.Singleton
                    ? BuildSingletonInstanceCreator(serviceType, provider)
                    : BuildScopedInstanceCreator(serviceType, options.ServiceProviderAccessor),
                options.Container);

            // This registration is managed and disposed by IServiceProvider and should, therefore, not be
            // disposed (again) by Simple Injector.
            registration.SuppressDisposal = true;

            if (lifestyle == Lifestyle.Transient && typeof(IDisposable).IsAssignableFrom(serviceType))
            {
                registration.SuppressDiagnosticWarning(
                    DiagnosticType.DisposableTransientComponent,
                    justification: "This is a cross-wired service. It will be disposed by IServiceScope.");
            }

            return(registration);
        }
        /// <summary>
        /// Finalizes the configuration of Simple Injector on top of <see cref="IServiceCollection"/>. Will
        /// ensure framework components can be injected into Simple Injector-resolved components, unless
        /// <see cref="SimpleInjectorUseOptions.AutoCrossWireFrameworkComponents"/> is set to <c>false</c>
        /// using the <paramref name="setupAction"/>.
        /// </summary>
        /// <param name="provider">The application's <see cref="IServiceProvider"/>.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <param name="setupAction">An optional setup action.</param>
        /// <returns>The supplied <paramref name="provider"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="provider"/> or
        /// <paramref name="container"/> are null references.</exception>
        public static IServiceProvider UseSimpleInjector(
            this IServiceProvider provider,
            Container container,
            Action <SimpleInjectorUseOptions> setupAction = null)
        {
            if (provider is null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            SimpleInjectorAddOptions addOptions = GetOptions(container);

            RegisterServiceScope(provider, container);

            var useOptions = new SimpleInjectorUseOptions(addOptions, provider);

            setupAction?.Invoke(useOptions);

            if (useOptions.AutoCrossWireFrameworkComponents)
            {
                AddAutoCrossWiring(container, provider, addOptions);
            }

            return(provider);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Finalizes the configuration of Simple Injector on top of <see cref="IServiceCollection"/>. Will
        /// ensure framework components can be injected into Simple Injector-resolved components, unless
        /// <see cref="SimpleInjectorUseOptions.AutoCrossWireFrameworkComponents"/> is set to <c>false</c>
        /// using the <paramref name="setupAction"/>.
        /// </summary>
        /// <param name="provider">The application's <see cref="IServiceProvider"/>.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <param name="setupAction">An optional setup action.</param>
        /// <returns>The supplied <paramref name="provider"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="provider"/> or
        /// <paramref name="container"/> are null references.</exception>
        //// I wanted to add this obsolete message in 4.8, but it was confusing considering the obsolete
        //// messages for everything on top of SimpleInjectorUseOptions. When those obsolete messages are
        //// resolved by the user, there is no harm in calling this method any longer. So it will get
        //// obsoleted in a later release.
        ////[Obsolete(
        ////    "You are supplying a setup action, but due breaking changes in ASP.NET Core 3, the Simple " +
        ////    "Injector container can get locked at an earlier stage, making it impossible to further setup " +
        ////    "the container at this stage. Please call the UseSimpleInjector(IServiceProvider, Container) " +
        ////    "overload instead. Take a look at the compiler warnings on the individual methods you are " +
        ////    "calling inside your setupAction delegate to understand how to migrate them. " +
        ////    " For more information, see: https://simpleinjector.org/aspnetcore. " +
        ////    "Will be treated as an error from version 4.10. Will be removed in version 5.0.",
        ////    error: false)]
        public static IServiceProvider UseSimpleInjector(
            this IServiceProvider provider,
            Container container,
            Action <SimpleInjectorUseOptions>?setupAction)
        {
            if (provider is null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            SimpleInjectorAddOptions addOptions = GetOptions(container);

            addOptions.SetServiceProviderIfNull(provider);

            var useOptions = new SimpleInjectorUseOptions(addOptions, provider);

            setupAction?.Invoke(useOptions);

            return(provider);
        }
    /// <summary>
    /// Registers a service to be executed by the `TimedHostedService`. The TimedHostedService executes the service repeatedly in a specified interval.
    /// </summary>
    public static void AddTimedHostedService <TService>(this SimpleInjectorAddOptions options, Action <TimedHostedServiceSettings> configureTimedHostedService, Func <TService, CancellationToken, Task> executeTask)
        where TService : class
    {
        var settings = new TimedHostedServiceSettings();

        configureTimedHostedService(settings);

        options.AddHostedService <TimedHostedService <TService> >();

        options.Container.Register <TService>();
        options.Container.RegisterInstance(new TimedHostedService <TService> .Settings(TimeSpan.FromSeconds(settings.Interval), settings.WatchdogUri, executeTask));
    }
Ejemplo n.º 11
0
 private static void EnsureMethodOnlyCalledOnce(
     SimpleInjectorAddOptions options, string methodName, object key)
 {
     if (options.Container.ContainerScope.GetItem(key) != null)
     {
         throw new InvalidOperationException(
                   $"The {methodName} extension method can only be called once on a Container instance.");
     }
     else
     {
         options.Container.ContainerScope.SetItem(key, new object());
     }
 }
Ejemplo n.º 12
0
        private static void AddSimpleInjectorOptions(Container container, SimpleInjectorAddOptions builder)
        {
            var current = container.ContainerScope.GetItem(AddOptionsKey);

            if (current is null)
            {
                container.ContainerScope.SetItem(AddOptionsKey, builder);
            }
            else
            {
                throw new InvalidOperationException(
                          $"The {nameof(AddSimpleInjector)} extension method can only be called once.");
            }
        }
Ejemplo n.º 13
0
        private static void HookAspNetCoreHostHostedServiceServiceProviderInitialization(
            SimpleInjectorAddOptions options)
        {
            // ASP.NET Core 3's new Host class resolves hosted services much earlier in the pipeline. This
            // registration ensures that the IServiceProvider is assigned before such resolve takes place,
            // to ensure that that hosted service can be injected with cross-wired dependencies.
            options.Services.AddSingleton <IHostedService>(provider =>
            {
                options.SetServiceProviderIfNull(provider);

                // We can't return null here, so we return an empty implementation.
                return(new NullSimpleInjectorHostedService());
            });
        }
        /// <summary>
        /// Sets up the basic configuration that allows Simple Injector to be used in frameworks that require
        /// the use of <see cref="IServiceCollection"/> for registration of framework components.
        /// In case of the absense of a
        /// <see cref="ContainerOptions.DefaultScopedLifestyle">DefaultScopedLifestyle</see>, this method
        /// will configure <see cref="AsyncScopedLifestyle"/> as the default scoped lifestyle.
        /// In case a <paramref name="setupAction"/> is supplied, that delegate will be called that allow
        /// further configuring the container.
        /// </summary>
        /// <param name="services">The framework's <see cref="IServiceCollection"/> instance.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <param name="setupAction">An optional setup action.</param>
        /// <returns>The supplied <paramref name="services"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="services"/> or
        /// <paramref name="container"/> are null references.</exception>
        public static IServiceCollection AddSimpleInjector(
            this IServiceCollection services,
            Container container,
            Action <SimpleInjectorAddOptions>?setupAction = null)
        {
            if (services is null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            var options = new SimpleInjectorAddOptions(
                services,
                container,
                new DefaultServiceProviderAccessor(container));

            // Add the container; this simplifies registration of types that depend on the container, but need
            // to be constructed by MS.DI (such as generic activators). Those registrations don't need to add
            // the container themselves.
            services.TryAddSingleton(container);

            // This stores the options, which includes the IServiceCollection. IServiceCollection is required
            // when calling UseSimpleInjector to enable auto cross wiring.
            AddSimpleInjectorOptions(container, options);

            // Set lifestyle before calling setupAction. Code in the delegate might depend on that.
            TrySetDefaultScopedLifestyle(container);

            HookAspNetCoreHostHostedServiceServiceProviderInitialization(options);

            setupAction?.Invoke(options);

            RegisterServiceScope(options);

            if (options.AutoCrossWireFrameworkComponents)
            {
                AddAutoCrossWiring(options);
            }

            if (options.DisposeContainerWithServiceProvider)
            {
                AddContainerDisposalOnShutdown(services, options);
            }

            return(services);
        }
        private static SimpleInjectorAddOptions GetOptions(Container container)
        {
            SimpleInjectorAddOptions options =
                (SimpleInjectorAddOptions)container.ContainerScope.GetItem(SimpleInjectorAddOptionsKey);

            if (options is null)
            {
                throw new InvalidOperationException(
                          "Please ensure the " +
                          $"{nameof(SimpleInjectorServiceCollectionExtensions.AddSimpleInjector)} extension " +
                          "method is called on the IServiceCollection instance before using this method.");
            }

            return(options);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Finalizes the configuration of Simple Injector on top of <see cref="IServiceCollection"/>. Will
        /// ensure framework components can be injected into Simple Injector-resolved components, unless
        /// <see cref="SimpleInjectorAddOptions.AutoCrossWireFrameworkComponents"/> is set to <c>false</c>.
        /// </summary>
        /// <param name="provider">The application's <see cref="IServiceProvider"/>.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <returns>The supplied <paramref name="provider"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="provider"/> or
        /// <paramref name="container"/> are null references.</exception>
        public static IServiceProvider UseSimpleInjector(this IServiceProvider provider, Container container)
        {
            if (provider is null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            SimpleInjectorAddOptions addOptions = GetOptions(container);

            addOptions.SetServiceProviderIfNull(provider);

            return(provider);
        }
        /// <summary>
        /// Registers the given <typeparamref name="THostedService"/> in the Container as Singleton and
        /// adds it to the host's pipeline of hosted services.
        /// </summary>
        /// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
        /// <param name="options">The options.</param>
        /// <returns>The <paramref name="options"/>.</returns>
        public static SimpleInjectorAddOptions AddHostedService <THostedService>(
            this SimpleInjectorAddOptions options)
            where THostedService : class, IHostedService
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var registration = Lifestyle.Singleton.CreateRegistration <THostedService>(options.Container);

            // Let the built-in configuration system dispose this instance.
            registration.SuppressDisposal = true;

            options.Container.AddRegistration <THostedService>(registration);

            options.Services.AddSingleton <IHostedService>(_ =>
            {
                try
                {
                    return(options.Container.GetInstance <THostedService>());
                }
                catch (ActivationException ex) when(ex.Message.Contains("is not registered"))
                {
                    throw new ActivationException(ex.Message + " " +
                                                  "ASP.NET Core is trying to resolve your " +
                                                  $"{typeof(THostedService).ToFriendlyName()} hosted service that you registered by " +
                                                  "calling the AddHostedService<THostedService>() extension method, but it can't be " +
                                                  "resolved due to a missing registration. In ASP.NET Core 3 and up, hosted " +
                                                  "services are resolved much earlier in the pipeline, before the 'Configure' " +
                                                  "method of your Startup class is invoked. If you are registering the missing " +
                                                  "service inside the 'Configure' method, that would be the likely cause of the " +
                                                  "issue. To fix the problem, you should ensure that all registration to the " +
                                                  "container are done during the 'ConfigureServices' method of the Startup class. " +
                                                  "For more information, see: https://simpleinjector.org/generichost or " +
                                                  "https://simpleinjector.org/aspnetcore.",
                                                  ex);
                }
            });

            return(options);
        }
        // Note about implementation: We could have used the ASP.NET Core IApplicationLifetime or
        // IHostApplicationLifetime for this as well, but there are a few downsides to this:
        // * IApplicationLifetime is obsolete
        // * IHostApplicationLifetime is only available for ASP.NET Core >= 3.0
        // * This requires ASP.NET Core, so this is less generic and couldn't be implemented in this library.
        // * It required much more research and testing to get right.
        private static void AddContainerDisposalOnShutdown(
            IServiceCollection services, SimpleInjectorAddOptions options)
        {
            services.TryAddSingleton(options.Container);

            // This wrapper implements disposable and allows the container to be disposed of when
            // IServiceProvider is disposed of. Just like Simple Injector, however, MS.DI will only
            // dispose of instances that are registered using this overload (not using AddSingleton<T>(T)).
            services.AddSingleton <ContainerDisposeWrapper>();

            options.Container.Options.ContainerLocking += (_, __) =>
            {
                // If there's no IServiceProvider, the property will throw, which is something we want to do
                // at this point, not later on, when an unregistered type is resolved.
                IServiceProvider provider = options.ApplicationServices;

                // In order for the wrapper to get disposed of, it needs to be resolved once.
                provider.GetRequiredService <ContainerDisposeWrapper>();
            };
        }
        /// <summary>
        /// Registers the given <typeparamref name="THostedService"/> in the Container as Singleton and
        /// adds it to the host's pipeline of hosted services.
        /// </summary>
        /// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
        /// <param name="options">The options.</param>
        /// <returns>The <paramref name="options"/>.</returns>
        public static SimpleInjectorAddOptions AddHostedService <THostedService>(
            this SimpleInjectorAddOptions options)
            where THostedService : class, IHostedService
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var registration = Lifestyle.Singleton.CreateRegistration <THostedService>(options.Container);

            // Let the built-in configuration system dispose this instance.
            registration.SuppressDisposal = true;

            options.Container.AddRegistration <THostedService>(registration);

            options.Services.AddSingleton <IHostedService>(
                _ => options.Container.GetInstance <THostedService>());

            return(options);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Sets up the basic configuration that allows Simple Injector to be used in frameworks that require
        /// the use of <see cref="IServiceCollection"/> for registration of framework components.
        /// In case of the absense of a
        /// <see cref="ContainerOptions.DefaultScopedLifestyle">DefaultScopedLifestyle</see>, this method
        /// will configure <see cref="AsyncScopedLifestyle"/> as the default scoped lifestyle.
        /// In case a <paramref name="setupAction"/> is supplied, that delegate will be called that allow
        /// further configuring the container.
        /// </summary>
        /// <param name="services">The framework's <see cref="IServiceCollection"/> instance.</param>
        /// <param name="container">The application's <see cref="Container"/> instance.</param>
        /// <param name="setupAction">An optional setup action.</param>
        /// <returns>The supplied <paramref name="services"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="services"/> or
        /// <paramref name="container"/> are null references.</exception>
        public static IServiceCollection AddSimpleInjector(
            this IServiceCollection services,
            Container container,
            Action <SimpleInjectorAddOptions>?setupAction = null)
        {
            if (services is null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            var options = new SimpleInjectorAddOptions(
                services,
                container,
                new DefaultServiceProviderAccessor(container));

            // This stores the options, which includes the IServiceCollection. IServiceCollection is required
            // when calling UseSimpleInjector to enable auto cross wiring.
            AddSimpleInjectorOptions(container, options);

            // Set lifestyle before calling setupAction. Code in the delegate might depend on that.
            TrySetDefaultScopedLifestyle(container);

            HookAspNetCoreHostHostedServiceServiceProviderInitialization(options);

            setupAction?.Invoke(options);

            RegisterServiceScope(options);

            if (options.AutoCrossWireFrameworkComponents)
            {
                AddAutoCrossWiring(options);
            }

            return(services);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Adds basic Simple Injector integration for ASP.NET Core and returns a builder object that allow
        /// additional integration options to be applied. These basic integrations includes wrapping each web
        /// request in an <see cref="AsyncScopedLifestyle"/> scope and making the nessesary changes that make
        /// it possible for enabling the injection of framework components in Simple Injector-constructed
        /// components when <see cref="SimpleInjectorServiceCollectionExtensions.UseSimpleInjector"/> is called.
        /// </summary>
        /// <param name="options">The options to which the integration should be applied.</param>
        /// <returns>A new <see cref="SimpleInjectorAspNetCoreBuilder"/> instance that allows additional
        /// configurations to be made.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
        public static SimpleInjectorAspNetCoreBuilder AddAspNetCore(this SimpleInjectorAddOptions options)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            IServiceCollection services = options.Services;

            var container = options.Container;

            // Add the IHttpContextAccessor to allow Simple Injector cross wiring to work in ASP.NET Core.
            services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            // Replace the default IServiceProviderAccessor with on that can use IHttpContextAccessor to
            // resolve instances that are scoped inside the current request.
            options.ServiceProviderAccessor = new AspNetCoreServiceProviderAccessor(
                new HttpContextAccessor(),
                options.ServiceProviderAccessor);

            services.UseSimpleInjectorAspNetRequestScoping(container);

            return(new SimpleInjectorAspNetCoreBuilder(options));
        }
Ejemplo n.º 22
0
 public void AddSimpleInjector(SimpleInjectorAddOptions options)
 {
     options.AddAspNetCore()
     .AddControllerActivation();
 }
Ejemplo n.º 23
0
 private static void RegisterServiceScope(SimpleInjectorAddOptions options)
 {
     options.Container.Register(
         () => options.ServiceScopeFactory.CreateScope(),
         Lifestyle.Scoped);
 }
Ejemplo n.º 24
0
 internal SimpleInjectorUseOptions(
     SimpleInjectorAddOptions builder, IServiceProvider applicationServices)
 {
     this.Builder             = builder;
     this.ApplicationServices = applicationServices;
 }
Ejemplo n.º 25
0
 /// <summary>
 /// Cross wires an ASP.NET Core or third-party service to the container, to allow the service to be
 /// injected into components that are built by Simple Injector.
 /// </summary>
 /// <typeparam name="TService">The type of service object to cross-wire.</typeparam>
 /// <param name="options">The options.</param>
 /// <returns>The supplied <paramref name="options"/>.</returns>
 /// <exception cref="ArgumentNullException">Thrown when the parameter is a null reference.
 /// </exception>
 public static SimpleInjectorAddOptions CrossWire <TService>(this SimpleInjectorAddOptions options)
     where TService : class
 {
     return(CrossWire(options, typeof(TService)));
 }
 internal SimpleInjectorAspNetCoreBuilder(SimpleInjectorAddOptions options)
 {
     this.options = options;
 }