Dependencyinjection: Precisa de suporte preguiçoso<t/>

Criado em 19 ago. 2014  ·  3Comentários  ·  Fonte: aspnet/DependencyInjection

DI deve suportar preguiçoso.
Não queremos instanciar imediatamente em algum momento.

Comentários muito úteis

É possível espalhar alguns métodos de extensão em IServiceCollection para adicionar suporte a Lazy com muito pouco esforço, sem exigir que todos os contêineres IoC suportem esse recurso. Pensamentos?

namespace Microsoft.Extensions.DependencyInjection
{
    using System;

    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> to the
        /// specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service to add.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddScoped<TService>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with a
        /// factory specified in <paramref name="implementationFactory"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddScoped(implementationFactory)
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with an
        /// implementation type specified in <typeparamref name="TImplementation"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddScoped<TService, TImplementation>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with an
        /// implementation type specified in <typeparamref name="TImplementation"/> using the factory specified in
        /// <paramref name="implementationFactory"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddScoped<TService, TImplementation>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> to the
        /// specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddSingleton<TService>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with a
        /// factory specified in <paramref name="implementationFactory"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddSingleton(implementationFactory)
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with
        /// an instance specified in implementationInstance to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationInstance">The implementation instance.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(
            this IServiceCollection services,
            TService implementationInstance)
            where TService : class
        {
            return services
                .AddSingleton<TService>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with
        /// an implementation type specified in <typeparamref name="TImplementation"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddSingleton<TService, TImplementation>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> using the factory specified in <paramref name="implementationFactory"/>
        /// to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddSingleton<TService, TImplementation>(implementationFactory)
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddTransient<TService>()
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with a factory specified
        /// in <paramref name="implementationFactory"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddTransient(implementationFactory)
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddTransient<TService, TImplementation>()
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> using the factory specified in <paramref name="implementationFactory"/>
        /// to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddTransient(implementationFactory)
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }
    }
}

Todos 3 comentários

Gosto dessa ideia, mas nem todos os contêineres IoC nos quais queremos que o ASP.NET seja executado oferecem suporte a isso. Por exemplo, parece que este recurso foi implementado como uma extensão do Ninject .

Se quiser usar Lazy<T> em seu aplicativo, você pode optar por usar um contêiner IoC completo, como Autofac ou Ninject (com a extensão).

É possível espalhar alguns métodos de extensão em IServiceCollection para adicionar suporte a Lazy com muito pouco esforço, sem exigir que todos os contêineres IoC suportem esse recurso. Pensamentos?

namespace Microsoft.Extensions.DependencyInjection
{
    using System;

    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> to the
        /// specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service to add.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddScoped<TService>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with a
        /// factory specified in <paramref name="implementationFactory"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddScoped(implementationFactory)
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with an
        /// implementation type specified in <typeparamref name="TImplementation"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddScoped<TService, TImplementation>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized scoped service of the type specified in <typeparamref name="TService"/> with an
        /// implementation type specified in <typeparamref name="TImplementation"/> using the factory specified in
        /// <paramref name="implementationFactory"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddScopedLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddScoped<TService, TImplementation>()
                .AddScoped(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> to the
        /// specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddSingleton<TService>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with a
        /// factory specified in <paramref name="implementationFactory"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddSingleton(implementationFactory)
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with
        /// an instance specified in implementationInstance to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationInstance">The implementation instance.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService>(
            this IServiceCollection services,
            TService implementationInstance)
            where TService : class
        {
            return services
                .AddSingleton<TService>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with
        /// an implementation type specified in <typeparamref name="TImplementation"/> to the specified
        /// <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddSingleton<TService, TImplementation>()
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized singleton service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> using the factory specified in <paramref name="implementationFactory"/>
        /// to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddSingletonLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddSingleton<TService, TImplementation>(implementationFactory)
                .AddSingleton(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService>(this IServiceCollection services)
            where TService : class
        {
            return services
                .AddTransient<TService>()
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with a factory specified
        /// in <paramref name="implementationFactory"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService>(
            this IServiceCollection services,
            Func<IServiceProvider, TService> implementationFactory)
            where TService : class
        {
            return services
                .AddTransient(implementationFactory)
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService, TImplementation>(this IServiceCollection services)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddTransient<TService, TImplementation>()
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }

        /// <summary>
        /// Adds a lazily initialized transient service of the type specified in <typeparamref name="TService"/> with an implementation
        /// type specified in <typeparamref name="TImplementation"/> using the factory specified in <paramref name="implementationFactory"/>
        /// to the specified <see cref="IServiceCollection"/>.
        /// </summary>
        /// <typeparam name="TService">The type of the service.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
        /// <param name="implementationFactory">The factory that creates the service.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddTransientLazy<TService, TImplementation>(
            this IServiceCollection services,
            Func<IServiceProvider, TImplementation> implementationFactory)
            where TService : class
            where TImplementation : class, TService
        {
            return services
                .AddTransient(implementationFactory)
                .AddTransient(x => new Lazy<TService>(() => x.GetRequiredService<TService>()));
        }
    }
}

@RehanSaeed essas extensões não funcionam ao tentar registrar várias implementações da mesma interface e usar GetServices

Esta página foi útil?
0 / 5 - 0 avaliações