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.
|
/// A list of services that are provided by this service. This allow other plugins to declare dependencies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// You should put directly the type that you will register in configure, Kyoo will detect by itself which
|
/// You should put the type's interface that will be register in configure.
|
||||||
/// interfaces are implemented by your type.
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
Type[] Provides { get; }
|
Type[] Provides { get; }
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LibraryManager"/> instancce with every repository available.
|
/// Create a new <see cref="LibraryManager"/> instance with every repository available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="repositories">The list of repositories that this library manager should manage.
|
/// <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>
|
/// 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)
|
if (_repositories.FirstOrDefault(x => x.RepositoryType == typeof(T)) is IRepository<T> ret)
|
||||||
return ret;
|
return ret;
|
||||||
throw new ItemNotFoundException();
|
throw new ItemNotFoundException($"No repository found for the type {typeof(T).Name}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -21,5 +21,46 @@ namespace Kyoo
|
|||||||
container.RegisterType<ITask, T>();
|
container.RegisterType<ITask, T>();
|
||||||
return container;
|
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 true;
|
||||||
return firstID == secondID;
|
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}>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -82,28 +82,17 @@ namespace Kyoo
|
|||||||
{
|
{
|
||||||
return Set<Link<T1, T2>>();
|
return Set<Link<T1, T2>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
|
|
||||||
/// </summary>
|
|
||||||
public DatabaseContext()
|
|
||||||
{
|
|
||||||
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
||||||
ChangeTracker.LazyLoadingEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="DatabaseContext"/>.
|
/// Set basic configurations (like preventing query tracking)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">Connection options to use (witch database provider to use, connection strings...)</param>
|
/// <param name="optionsBuilder">An option builder to fill.</param>
|
||||||
public DatabaseContext(DbContextOptions<DatabaseContext> options)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
: base(options)
|
|
||||||
{
|
{
|
||||||
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
base.OnConfiguring(optionsBuilder);
|
||||||
ChangeTracker.LazyLoadingEnabled = false;
|
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set database parameters to support every types of Kyoo.
|
/// Set database parameters to support every types of Kyoo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -51,6 +51,7 @@ namespace Kyoo.Postgresql
|
|||||||
if (_debugMode)
|
if (_debugMode)
|
||||||
optionsBuilder.EnableDetailedErrors()
|
optionsBuilder.EnableDetailedErrors()
|
||||||
.EnableSensitiveDataLogging();
|
.EnableSensitiveDataLogging();
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -66,6 +66,11 @@ namespace Kyoo.Controllers
|
|||||||
_configuration = configuration.GetSection("scheduledTasks");
|
_configuration = configuration.GetSection("scheduledTasks");
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_tasks = tasks.Select(x => (x, DateTime.Now + GetTaskDelay(x.Slug))).ToList();
|
_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 />
|
/// <inheritdoc />
|
||||||
public Type[] Provides => new[]
|
public Type[] Provides => new[]
|
||||||
{
|
{
|
||||||
typeof(FileManager),
|
typeof(IFileManager),
|
||||||
typeof(Transcoder),
|
typeof(ITranscoder),
|
||||||
typeof(ThumbnailsManager),
|
typeof(IThumbnailsManager),
|
||||||
typeof(ProviderManager),
|
typeof(IProviderManager),
|
||||||
typeof(TaskManager),
|
typeof(ITaskManager),
|
||||||
typeof(LibraryManager),
|
typeof(ILibraryManager),
|
||||||
typeof(LibraryRepository),
|
typeof(ILibraryRepository),
|
||||||
typeof(LibraryItemRepository),
|
typeof(ILibraryItemRepository),
|
||||||
typeof(CollectionRepository),
|
typeof(ICollectionRepository),
|
||||||
typeof(ShowRepository),
|
typeof(IShowRepository),
|
||||||
typeof(SeasonRepository),
|
typeof(ISeasonRepository),
|
||||||
typeof(EpisodeRepository),
|
typeof(IEpisodeRepository),
|
||||||
typeof(TrackRepository),
|
typeof(ITrackRepository),
|
||||||
typeof(PeopleRepository),
|
typeof(IPeopleRepository),
|
||||||
typeof(StudioRepository),
|
typeof(IStudioRepository),
|
||||||
typeof(GenreRepository),
|
typeof(IGenreRepository),
|
||||||
typeof(ProviderRepository),
|
typeof(IProviderRepository)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -62,17 +62,17 @@ namespace Kyoo
|
|||||||
|
|
||||||
container.RegisterType<ILibraryManager, LibraryManager>(new HierarchicalLifetimeManager());
|
container.RegisterType<ILibraryManager, LibraryManager>(new HierarchicalLifetimeManager());
|
||||||
|
|
||||||
container.RegisterType<ILibraryRepository, LibraryRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<ILibraryRepository, LibraryRepository>();
|
||||||
container.RegisterType<ILibraryItemRepository, LibraryItemRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<ILibraryItemRepository, LibraryItemRepository>();
|
||||||
container.RegisterType<ICollectionRepository, CollectionRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<ICollectionRepository, CollectionRepository>();
|
||||||
container.RegisterType<IShowRepository, ShowRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IShowRepository, ShowRepository>();
|
||||||
container.RegisterType<ISeasonRepository, SeasonRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<ISeasonRepository, SeasonRepository>();
|
||||||
container.RegisterType<IEpisodeRepository, EpisodeRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IEpisodeRepository, EpisodeRepository>();
|
||||||
container.RegisterType<ITrackRepository, TrackRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<ITrackRepository, TrackRepository>();
|
||||||
container.RegisterType<IPeopleRepository, PeopleRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IPeopleRepository, PeopleRepository>();
|
||||||
container.RegisterType<IStudioRepository, StudioRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IStudioRepository, StudioRepository>();
|
||||||
container.RegisterType<IGenreRepository, GenreRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IGenreRepository, GenreRepository>();
|
||||||
container.RegisterType<IProviderRepository, ProviderRepository>(new HierarchicalLifetimeManager());
|
container.RegisterRepository<IProviderRepository, ProviderRepository>();
|
||||||
|
|
||||||
container.RegisterTask<Crawler>();
|
container.RegisterTask<Crawler>();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.UnityExtensions;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
|
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -8,7 +9,6 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Unity;
|
using Unity;
|
||||||
using Unity.Microsoft.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
@ -46,16 +46,16 @@ namespace Kyoo
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Console.WriteLine($"Running as {Environment.UserName}.");
|
Console.WriteLine($"Running as {Environment.UserName}.");
|
||||||
IWebHostBuilder host = CreateWebHostBuilder(args);
|
IWebHostBuilder builder = CreateWebHostBuilder(args);
|
||||||
if (debug != null)
|
if (debug != null)
|
||||||
host = host.UseEnvironment(debug == true ? "Development" : "Production");
|
builder = builder.UseEnvironment(debug == true ? "Development" : "Production");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await host.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
new Logger<Startup>(new LoggerFactory()).LogCritical(ex, "Unhandled exception");
|
await Console.Error.WriteLineAsync($"Unhandled exception: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ namespace Kyoo
|
|||||||
.AddEnvironmentVariables()
|
.AddEnvironmentVariables()
|
||||||
.AddCommandLine(args);
|
.AddCommandLine(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a a web host
|
/// Create a a web host
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -80,8 +80,8 @@ namespace Kyoo
|
|||||||
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
|
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
|
||||||
{
|
{
|
||||||
UnityContainer container = new();
|
UnityContainer container = new();
|
||||||
container.EnableDebugDiagnostic();
|
// container.EnableDebugDiagnostic();
|
||||||
|
|
||||||
return new WebHostBuilder()
|
return new WebHostBuilder()
|
||||||
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
|
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
|
||||||
.UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build())
|
.UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build())
|
||||||
@ -99,7 +99,7 @@ namespace Kyoo
|
|||||||
if (context.HostingEnvironment.IsDevelopment())
|
if (context.HostingEnvironment.IsDevelopment())
|
||||||
StaticWebAssetsLoader.UseStaticWebAssets(context.HostingEnvironment, context.Configuration);
|
StaticWebAssetsLoader.UseStaticWebAssets(context.HostingEnvironment, context.Configuration);
|
||||||
})
|
})
|
||||||
.UseUnityServiceProvider(container)
|
.UseUnityProvider(container)
|
||||||
.ConfigureServices(x => x.AddRouting())
|
.ConfigureServices(x => x.AddRouting())
|
||||||
.UseKestrel(options => { options.AddServerHeader = false; })
|
.UseKestrel(options => { options.AddServerHeader = false; })
|
||||||
.UseIIS()
|
.UseIIS()
|
||||||
|
@ -142,11 +142,18 @@ namespace Kyoo
|
|||||||
{
|
{
|
||||||
AllowedOrigins = { new Uri(publicUrl).GetLeftPart(UriPartial.Authority) }
|
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 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)
|
public void Configure(IUnityContainer container, IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
@ -213,12 +220,9 @@ namespace Kyoo
|
|||||||
});
|
});
|
||||||
|
|
||||||
container.RegisterType<IPluginManager, PluginManager>(new SingletonLifetimeManager());
|
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();
|
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