mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Fixing the unity container
This commit is contained in:
parent
c0f1f80a40
commit
36220613ab
@ -32,8 +32,7 @@ namespace Kyoo.Controllers
|
||||
/// A list of services that are provided by this service. This allow other plugins to declare dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You should put directly the type that you will register in configure, Kyoo will detect by itself which
|
||||
/// interfaces are implemented by your type.
|
||||
/// You should put the type's interface that will be register in configure.
|
||||
/// </remarks>
|
||||
Type[] Provides { get; }
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace Kyoo.Controllers
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LibraryManager"/> instancce with every repository available.
|
||||
/// Create a new <see cref="LibraryManager"/> instance with every repository available.
|
||||
/// </summary>
|
||||
/// <param name="repositories">The list of repositories that this library manager should manage.
|
||||
/// If a repository for every base type is not available, this instance won't be stable.</param>
|
||||
@ -66,7 +66,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
if (_repositories.FirstOrDefault(x => x.RepositoryType == typeof(T)) is IRepository<T> ret)
|
||||
return ret;
|
||||
throw new ItemNotFoundException();
|
||||
throw new ItemNotFoundException($"No repository found for the type {typeof(T).Name}.");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -21,5 +21,46 @@ namespace Kyoo
|
||||
container.RegisterType<ITask, T>();
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new repository to the container.
|
||||
/// </summary>
|
||||
/// <param name="container">The container</param>
|
||||
/// <typeparam name="T">The type of the repository.</typeparam>
|
||||
/// <remarks>
|
||||
/// If your repository implements a special interface, please use <see cref="RegisterRepository{T,T}"/>
|
||||
/// </remarks>
|
||||
/// <returns>The initial container.</returns>
|
||||
public static IUnityContainer RegisterRepository<T>(this IUnityContainer container)
|
||||
where T : IBaseRepository
|
||||
{
|
||||
Type repository = Utility.GetGenericDefinition(typeof(T), typeof(IRepository<>));
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
container.RegisterType(repository, typeof(T));
|
||||
container.RegisterType<IBaseRepository, T>(repository.FriendlyName());
|
||||
}
|
||||
else
|
||||
container.RegisterType<IBaseRepository, T>(typeof(T).FriendlyName());
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new repository with a custom mapping to the container.
|
||||
/// </summary>
|
||||
/// <param name="container"></param>
|
||||
/// <typeparam name="T">The custom mapping you have for your repository.</typeparam>
|
||||
/// <typeparam name="T2">The type of the repository.</typeparam>
|
||||
/// <remarks>
|
||||
/// If your repository does not implements a special interface, please use <see cref="RegisterRepository{T}"/>
|
||||
/// </remarks>
|
||||
/// <returns>The initial container.</returns>
|
||||
public static IUnityContainer RegisterRepository<T, T2>(this IUnityContainer container)
|
||||
where T2 : IBaseRepository, T
|
||||
{
|
||||
container.RegisterType<T, T2>();
|
||||
return container.RegisterRepository<T2>();
|
||||
}
|
||||
}
|
||||
}
|
@ -777,5 +777,19 @@ namespace Kyoo
|
||||
return true;
|
||||
return firstID == secondID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a friendly type name (supporting generics)
|
||||
/// For example a list of string will be displayed as List<string> and not as List`1.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to use</param>
|
||||
/// <returns>The friendly name of the type</returns>
|
||||
public static string FriendlyName(this Type type)
|
||||
{
|
||||
if (!type.IsGenericType)
|
||||
return type.Name;
|
||||
string generics = string.Join(", ", type.GetGenericArguments().Select(x => x.FriendlyName()));
|
||||
return $"{type.Name[..type.Name.IndexOf('`')]}<{generics}>";
|
||||
}
|
||||
}
|
||||
}
|
@ -83,25 +83,14 @@ namespace Kyoo
|
||||
return Set<Link<T1, T2>>();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
|
||||
/// Set basic configurations (like preventing query tracking)
|
||||
/// </summary>
|
||||
public DatabaseContext()
|
||||
/// <param name="optionsBuilder">An option builder to fill.</param>
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
ChangeTracker.LazyLoadingEnabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="DatabaseContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">Connection options to use (witch database provider to use, connection strings...)</param>
|
||||
public DatabaseContext(DbContextOptions<DatabaseContext> options)
|
||||
: base(options)
|
||||
{
|
||||
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
ChangeTracker.LazyLoadingEnabled = false;
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,6 +51,7 @@ namespace Kyoo.Postgresql
|
||||
if (_debugMode)
|
||||
optionsBuilder.EnableDetailedErrors()
|
||||
.EnableSensitiveDataLogging();
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -66,6 +66,11 @@ namespace Kyoo.Controllers
|
||||
_configuration = configuration.GetSection("scheduledTasks");
|
||||
_logger = logger;
|
||||
_tasks = tasks.Select(x => (x, DateTime.Now + GetTaskDelay(x.Slug))).ToList();
|
||||
|
||||
if (_tasks.Any())
|
||||
_logger.LogTrace("Task manager initiated with: {Tasks}", _tasks.Select(x => x.task.Name));
|
||||
else
|
||||
_logger.LogInformation("Task manager initiated without any tasks");
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,23 +23,23 @@ namespace Kyoo
|
||||
/// <inheritdoc />
|
||||
public Type[] Provides => new[]
|
||||
{
|
||||
typeof(FileManager),
|
||||
typeof(Transcoder),
|
||||
typeof(ThumbnailsManager),
|
||||
typeof(ProviderManager),
|
||||
typeof(TaskManager),
|
||||
typeof(LibraryManager),
|
||||
typeof(LibraryRepository),
|
||||
typeof(LibraryItemRepository),
|
||||
typeof(CollectionRepository),
|
||||
typeof(ShowRepository),
|
||||
typeof(SeasonRepository),
|
||||
typeof(EpisodeRepository),
|
||||
typeof(TrackRepository),
|
||||
typeof(PeopleRepository),
|
||||
typeof(StudioRepository),
|
||||
typeof(GenreRepository),
|
||||
typeof(ProviderRepository),
|
||||
typeof(IFileManager),
|
||||
typeof(ITranscoder),
|
||||
typeof(IThumbnailsManager),
|
||||
typeof(IProviderManager),
|
||||
typeof(ITaskManager),
|
||||
typeof(ILibraryManager),
|
||||
typeof(ILibraryRepository),
|
||||
typeof(ILibraryItemRepository),
|
||||
typeof(ICollectionRepository),
|
||||
typeof(IShowRepository),
|
||||
typeof(ISeasonRepository),
|
||||
typeof(IEpisodeRepository),
|
||||
typeof(ITrackRepository),
|
||||
typeof(IPeopleRepository),
|
||||
typeof(IStudioRepository),
|
||||
typeof(IGenreRepository),
|
||||
typeof(IProviderRepository)
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -62,17 +62,17 @@ namespace Kyoo
|
||||
|
||||
container.RegisterType<ILibraryManager, LibraryManager>(new HierarchicalLifetimeManager());
|
||||
|
||||
container.RegisterType<ILibraryRepository, LibraryRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<ILibraryItemRepository, LibraryItemRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<ICollectionRepository, CollectionRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IShowRepository, ShowRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<ISeasonRepository, SeasonRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IEpisodeRepository, EpisodeRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<ITrackRepository, TrackRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IPeopleRepository, PeopleRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IStudioRepository, StudioRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IGenreRepository, GenreRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterType<IProviderRepository, ProviderRepository>(new HierarchicalLifetimeManager());
|
||||
container.RegisterRepository<ILibraryRepository, LibraryRepository>();
|
||||
container.RegisterRepository<ILibraryItemRepository, LibraryItemRepository>();
|
||||
container.RegisterRepository<ICollectionRepository, CollectionRepository>();
|
||||
container.RegisterRepository<IShowRepository, ShowRepository>();
|
||||
container.RegisterRepository<ISeasonRepository, SeasonRepository>();
|
||||
container.RegisterRepository<IEpisodeRepository, EpisodeRepository>();
|
||||
container.RegisterRepository<ITrackRepository, TrackRepository>();
|
||||
container.RegisterRepository<IPeopleRepository, PeopleRepository>();
|
||||
container.RegisterRepository<IStudioRepository, StudioRepository>();
|
||||
container.RegisterRepository<IGenreRepository, GenreRepository>();
|
||||
container.RegisterRepository<IProviderRepository, ProviderRepository>();
|
||||
|
||||
container.RegisterTask<Crawler>();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.UnityExtensions;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -8,7 +9,6 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Unity;
|
||||
using Unity.Microsoft.DependencyInjection;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
@ -46,16 +46,16 @@ namespace Kyoo
|
||||
#endif
|
||||
|
||||
Console.WriteLine($"Running as {Environment.UserName}.");
|
||||
IWebHostBuilder host = CreateWebHostBuilder(args);
|
||||
IWebHostBuilder builder = CreateWebHostBuilder(args);
|
||||
if (debug != null)
|
||||
host = host.UseEnvironment(debug == true ? "Development" : "Production");
|
||||
builder = builder.UseEnvironment(debug == true ? "Development" : "Production");
|
||||
try
|
||||
{
|
||||
await host.Build().RunAsync();
|
||||
await builder.Build().RunAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
new Logger<Startup>(new LoggerFactory()).LogCritical(ex, "Unhandled exception");
|
||||
await Console.Error.WriteLineAsync($"Unhandled exception: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ namespace Kyoo
|
||||
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
|
||||
{
|
||||
UnityContainer container = new();
|
||||
container.EnableDebugDiagnostic();
|
||||
// container.EnableDebugDiagnostic();
|
||||
|
||||
return new WebHostBuilder()
|
||||
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
|
||||
@ -99,7 +99,7 @@ namespace Kyoo
|
||||
if (context.HostingEnvironment.IsDevelopment())
|
||||
StaticWebAssetsLoader.UseStaticWebAssets(context.HostingEnvironment, context.Configuration);
|
||||
})
|
||||
.UseUnityServiceProvider(container)
|
||||
.UseUnityProvider(container)
|
||||
.ConfigureServices(x => x.AddRouting())
|
||||
.UseKestrel(options => { options.AddServerHeader = false; })
|
||||
.UseIIS()
|
||||
|
@ -142,11 +142,18 @@ namespace Kyoo
|
||||
{
|
||||
AllowedOrigins = { new Uri(publicUrl).GetLeftPart(UriPartial.Authority) }
|
||||
});
|
||||
|
||||
services.AddSingleton<ITaskManager, TaskManager>();
|
||||
services.AddHostedService(x => x.GetService<ITaskManager>() as TaskManager);
|
||||
}
|
||||
|
||||
public void ConfigureContainer(IUnityContainer container)
|
||||
public void ConfigureContainer(UnityContainer container)
|
||||
{
|
||||
// TODO move this to the configure section and figure out a way to reload ControllerActivators with the updated unity container
|
||||
|
||||
// TODO the reload should re inject components from the constructor.
|
||||
// TODO fin a way to inject tasks without a IUnityContainer.
|
||||
// container.RegisterFactory<IHostedService>(c => c.Resolve<ITaskManager>(), new SingletonLifetimeManager());
|
||||
}
|
||||
|
||||
public void Configure(IUnityContainer container, IApplicationBuilder app, IWebHostEnvironment env)
|
||||
@ -213,12 +220,9 @@ namespace Kyoo
|
||||
});
|
||||
|
||||
container.RegisterType<IPluginManager, PluginManager>(new SingletonLifetimeManager());
|
||||
IPluginManager pluginManager = new PluginManager(container, _configuration, new Logger<PluginManager>(_loggerFactory));
|
||||
// container.Resolve<IConfiguration>();
|
||||
IPluginManager pluginManager = container.Resolve<IPluginManager>();
|
||||
pluginManager.ReloadPlugins();
|
||||
|
||||
// TODO the reload should re inject components from the constructor.
|
||||
// TODO fin a way to inject tasks without a IUnityContainer.
|
||||
container.RegisterFactory<IHostedService>(c => c.Resolve<ITaskManager>(), new SingletonLifetimeManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
Kyoo/UnityExtensions/UnityExtensions.cs
Normal file
32
Kyoo/UnityExtensions/UnityExtensions.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Unity;
|
||||
using Unity.Microsoft.DependencyInjection;
|
||||
|
||||
namespace Kyoo.UnityExtensions
|
||||
{
|
||||
public static class UnityExtensions
|
||||
{
|
||||
public static IWebHostBuilder UseUnityProvider(this IWebHostBuilder host, UnityContainer container)
|
||||
{
|
||||
UnityProvider factory = new(container);
|
||||
|
||||
return host.ConfigureServices((_, services) =>
|
||||
{
|
||||
services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<UnityContainer>>(factory));
|
||||
services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IUnityContainer>>(factory));
|
||||
services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(factory));
|
||||
});
|
||||
}
|
||||
|
||||
public static IUnityContainer AddServices(this IUnityContainer container, IServiceCollection services)
|
||||
{
|
||||
return (IUnityContainer)typeof(ServiceProviderExtensions).Assembly
|
||||
.GetType("Unity.Microsoft.DependencyInjection.Configuration")
|
||||
!.GetMethod("AddServices", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
!.Invoke(null, new object[] {container, services});
|
||||
}
|
||||
}
|
||||
}
|
30
Kyoo/UnityExtensions/UnityProvider.cs
Normal file
30
Kyoo/UnityExtensions/UnityProvider.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Unity;
|
||||
using Unity.Microsoft.DependencyInjection;
|
||||
|
||||
namespace Kyoo.UnityExtensions
|
||||
{
|
||||
public class UnityProvider : ServiceProviderFactory, IServiceProviderFactory<UnityContainer>
|
||||
{
|
||||
private readonly UnityContainer _container;
|
||||
|
||||
|
||||
public UnityProvider(UnityContainer container)
|
||||
: base(container)
|
||||
{
|
||||
_container = container;
|
||||
}
|
||||
|
||||
public UnityContainer CreateBuilder(IServiceCollection services)
|
||||
{
|
||||
_container.AddServices(services);
|
||||
return _container;
|
||||
}
|
||||
|
||||
public IServiceProvider CreateServiceProvider(UnityContainer containerBuilder)
|
||||
{
|
||||
return CreateServiceProvider(containerBuilder as IUnityContainer);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user