Simplify lazy creation

This commit is contained in:
Zoe Roux 2024-04-02 23:14:01 +02:00
parent 7ee28f4557
commit 8a639a3aee
No known key found for this signature in database
2 changed files with 2 additions and 50 deletions

View File

@ -20,7 +20,6 @@ using System;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Core.Controllers;
using Kyoo.Core.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
@ -39,7 +38,8 @@ public static class CoreModule
where TRepo : class, IRepository<T>
{
services.AddScoped<TRepo>();
services.AddScoped<IRepository<T>>(x => x.GetRequiredService<TRepo>()).AllowLazy();
services.AddScoped<IRepository<T>>(x => x.GetRequiredService<TRepo>());
services.AddScoped<Lazy<IRepository<T>>>(x => new(() => x.GetRequiredService<TRepo>()));
}
public static void ConfigureKyoo(this WebApplicationBuilder builder)

View File

@ -85,52 +85,4 @@ public static class ServiceExtensions
services.AddProxies();
services.AddHttpClient();
}
// Stollen from https://stackoverflow.com/questions/44934511/does-net-core-dependency-injection-support-lazyt
public static IServiceCollection AllowLazy(this IServiceCollection services)
{
ServiceDescriptor lastRegistration = services.Last();
Type serviceType = lastRegistration.ServiceType;
// The constructor for Lazy<T> expects a Func<T> which is hard to create dynamically.
Type lazyServiceType = typeof(Lazy<>).MakeGenericType(serviceType);
// Create a typed MethodInfo for `serviceProvider.GetRequiredService<T>`,
// where T has been resolved to the required ServiceType
System.Reflection.MethodInfo? getRequiredServiceMethod = typeof(ServiceProviderServiceExtensions).GetMethod(
nameof(ServiceProviderServiceExtensions.GetRequiredService),
1,
[typeof(IServiceProvider)]
);
System.Reflection.MethodInfo? getRequiredServiceMethodTyped = getRequiredServiceMethod?.MakeGenericMethod(
serviceType
);
// Now create a lambda expression equivalent to:
//
// serviceProvider => serviceProvider.GetRequiredService<T>();
//
ParameterExpression parameterExpr = Expression.Parameter(typeof(IServiceProvider), "serviceLocator");
LambdaExpression lambda = Expression.Lambda(
Expression.Call(null, getRequiredServiceMethodTyped!, parameterExpr),
parameterExpr
);
Delegate lambdaCompiled = lambda.Compile();
services.Add(
new ServiceDescriptor(
lazyServiceType,
serviceProvider =>
Activator.CreateInstance(
lazyServiceType,
lambdaCompiled.DynamicInvoke(serviceProvider)
)!,
lastRegistration.Lifetime
)
);
return services;
}
}