diff --git a/Kyoo.Common/Controllers/IPlugin.cs b/Kyoo.Common/Controllers/IPlugin.cs
index 56797bb2..a2f9d1b0 100644
--- a/Kyoo.Common/Controllers/IPlugin.cs
+++ b/Kyoo.Common/Controllers/IPlugin.cs
@@ -32,8 +32,7 @@ namespace Kyoo.Controllers
/// A list of services that are provided by this service. This allow other plugins to declare dependencies.
///
///
- /// 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.
///
Type[] Provides { get; }
diff --git a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
index dcf35813..ce34f267 100644
--- a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
+++ b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
@@ -40,7 +40,7 @@ namespace Kyoo.Controllers
///
- /// Create a new instancce with every repository available.
+ /// Create a new instance with every repository available.
///
/// 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.
@@ -66,7 +66,7 @@ namespace Kyoo.Controllers
{
if (_repositories.FirstOrDefault(x => x.RepositoryType == typeof(T)) is IRepository ret)
return ret;
- throw new ItemNotFoundException();
+ throw new ItemNotFoundException($"No repository found for the type {typeof(T).Name}.");
}
///
diff --git a/Kyoo.Common/Module.cs b/Kyoo.Common/Module.cs
index 639e7c2a..5ce34cbe 100644
--- a/Kyoo.Common/Module.cs
+++ b/Kyoo.Common/Module.cs
@@ -21,5 +21,46 @@ namespace Kyoo
container.RegisterType();
return container;
}
+
+ ///
+ /// Register a new repository to the container.
+ ///
+ /// The container
+ /// The type of the repository.
+ ///
+ /// If your repository implements a special interface, please use
+ ///
+ /// The initial container.
+ public static IUnityContainer RegisterRepository(this IUnityContainer container)
+ where T : IBaseRepository
+ {
+ Type repository = Utility.GetGenericDefinition(typeof(T), typeof(IRepository<>));
+
+ if (repository != null)
+ {
+ container.RegisterType(repository, typeof(T));
+ container.RegisterType(repository.FriendlyName());
+ }
+ else
+ container.RegisterType(typeof(T).FriendlyName());
+ return container;
+ }
+
+ ///
+ /// Register a new repository with a custom mapping to the container.
+ ///
+ ///
+ /// The custom mapping you have for your repository.
+ /// The type of the repository.
+ ///
+ /// If your repository does not implements a special interface, please use
+ ///
+ /// The initial container.
+ public static IUnityContainer RegisterRepository(this IUnityContainer container)
+ where T2 : IBaseRepository, T
+ {
+ container.RegisterType();
+ return container.RegisterRepository();
+ }
}
}
\ No newline at end of file
diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs
index 3e4bba15..2469afbc 100644
--- a/Kyoo.Common/Utility.cs
+++ b/Kyoo.Common/Utility.cs
@@ -777,5 +777,19 @@ namespace Kyoo
return true;
return firstID == secondID;
}
+
+ ///
+ /// Get a friendly type name (supporting generics)
+ /// For example a list of string will be displayed as List<string> and not as List`1.
+ ///
+ /// The type to use
+ /// The friendly name of the type
+ 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}>";
+ }
}
}
\ No newline at end of file
diff --git a/Kyoo.CommonAPI/DatabaseContext.cs b/Kyoo.CommonAPI/DatabaseContext.cs
index caf8933e..997b7bd4 100644
--- a/Kyoo.CommonAPI/DatabaseContext.cs
+++ b/Kyoo.CommonAPI/DatabaseContext.cs
@@ -82,28 +82,17 @@ namespace Kyoo
{
return Set>();
}
-
-
- ///
- /// A basic constructor that set default values (query tracker behaviors, mapping enums...)
- ///
- public DatabaseContext()
- {
- ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
- ChangeTracker.LazyLoadingEnabled = false;
- }
///
- /// Create a new .
+ /// Set basic configurations (like preventing query tracking)
///
- /// Connection options to use (witch database provider to use, connection strings...)
- public DatabaseContext(DbContextOptions options)
- : base(options)
+ /// An option builder to fill.
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
- ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
- ChangeTracker.LazyLoadingEnabled = false;
+ base.OnConfiguring(optionsBuilder);
+ optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
-
+
///
/// Set database parameters to support every types of Kyoo.
///
diff --git a/Kyoo.Postgresql/PostgresContext.cs b/Kyoo.Postgresql/PostgresContext.cs
index 7ee49adb..826b88e5 100644
--- a/Kyoo.Postgresql/PostgresContext.cs
+++ b/Kyoo.Postgresql/PostgresContext.cs
@@ -51,6 +51,7 @@ namespace Kyoo.Postgresql
if (_debugMode)
optionsBuilder.EnableDetailedErrors()
.EnableSensitiveDataLogging();
+ base.OnConfiguring(optionsBuilder);
}
///
diff --git a/Kyoo/Controllers/TaskManager.cs b/Kyoo/Controllers/TaskManager.cs
index 6f9c184b..89cff352 100644
--- a/Kyoo/Controllers/TaskManager.cs
+++ b/Kyoo/Controllers/TaskManager.cs
@@ -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");
}
diff --git a/Kyoo/CoreModule.cs b/Kyoo/CoreModule.cs
index 5916f33f..a32689a5 100644
--- a/Kyoo/CoreModule.cs
+++ b/Kyoo/CoreModule.cs
@@ -23,23 +23,23 @@ namespace Kyoo
///
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)
};
///
@@ -62,17 +62,17 @@ namespace Kyoo
container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
- container.RegisterType(new HierarchicalLifetimeManager());
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
+ container.RegisterRepository();
container.RegisterTask();
}
diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs
index e5053735..4d749a0f 100644
--- a/Kyoo/Program.cs
+++ b/Kyoo/Program.cs
@@ -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(new LoggerFactory()).LogCritical(ex, "Unhandled exception");
+ await Console.Error.WriteLineAsync($"Unhandled exception: {ex}");
}
}
@@ -71,7 +71,7 @@ namespace Kyoo
.AddEnvironmentVariables()
.AddCommandLine(args);
}
-
+
///
/// Create a a web host
///
@@ -80,8 +80,8 @@ namespace Kyoo
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
UnityContainer container = new();
- container.EnableDebugDiagnostic();
-
+ // container.EnableDebugDiagnostic();
+
return new WebHostBuilder()
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build())
@@ -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()
diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs
index 0fc391d1..1bdf23b2 100644
--- a/Kyoo/Startup.cs
+++ b/Kyoo/Startup.cs
@@ -142,11 +142,18 @@ namespace Kyoo
{
AllowedOrigins = { new Uri(publicUrl).GetLeftPart(UriPartial.Authority) }
});
+
+ services.AddSingleton();
+ services.AddHostedService(x => x.GetService() 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(c => c.Resolve(), new SingletonLifetimeManager());
}
public void Configure(IUnityContainer container, IApplicationBuilder app, IWebHostEnvironment env)
@@ -213,12 +220,9 @@ namespace Kyoo
});
container.RegisterType(new SingletonLifetimeManager());
- IPluginManager pluginManager = new PluginManager(container, _configuration, new Logger(_loggerFactory));
+ // container.Resolve();
+ IPluginManager pluginManager = container.Resolve();
pluginManager.ReloadPlugins();
-
- // TODO the reload should re inject components from the constructor.
- // TODO fin a way to inject tasks without a IUnityContainer.
- container.RegisterFactory(c => c.Resolve(), new SingletonLifetimeManager());
}
}
}
diff --git a/Kyoo/UnityExtensions/UnityExtensions.cs b/Kyoo/UnityExtensions/UnityExtensions.cs
new file mode 100644
index 00000000..b351ec8e
--- /dev/null
+++ b/Kyoo/UnityExtensions/UnityExtensions.cs
@@ -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>(factory));
+ services.Replace(ServiceDescriptor.Singleton>(factory));
+ services.Replace(ServiceDescriptor.Singleton>(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});
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo/UnityExtensions/UnityProvider.cs b/Kyoo/UnityExtensions/UnityProvider.cs
new file mode 100644
index 00000000..93d460f0
--- /dev/null
+++ b/Kyoo/UnityExtensions/UnityProvider.cs
@@ -0,0 +1,30 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Unity;
+using Unity.Microsoft.DependencyInjection;
+
+namespace Kyoo.UnityExtensions
+{
+ public class UnityProvider : ServiceProviderFactory, IServiceProviderFactory
+ {
+ 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);
+ }
+ }
+}
\ No newline at end of file