DI 应该支持 Lazy
我们不想在某个时候立即实例化。
我喜欢这个想法,但并非我们希望 ASP.NET 运行的所有 IoC 容器都支持这一点。 例如,看起来这个功能是作为 Ninject 的扩展实现的。
如果您想在您的应用程序中使用Lazy<T>
,您可以选择使用功能齐全的 IoC 容器,例如 Autofac 或 Ninject(带有扩展名)。
可以在IServiceCollection
上撒一些扩展方法来添加 Lazy 支持,而无需所有 IoC 容器都支持此功能。 想法?
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这些扩展在尝试注册同一接口的多个实现并使用 GetServices 时不起作用
最有用的评论
可以在
IServiceCollection
上撒一些扩展方法来添加 Lazy 支持,而无需所有 IoC 容器都支持此功能。 想法?