mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Detect RSS builders automatically via reflection
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Podsync.Services.Feed;
|
||||
using Podsync.Services.Links;
|
||||
@@ -10,13 +14,15 @@ namespace Podsync.Services.Builder
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
public class CompositeRssBuilder : RssBuilderBase
|
||||
{
|
||||
private readonly YouTubeRssBuilder _youTubeBuilder;
|
||||
private readonly VimeoRssBuilder _vimeoBuilder;
|
||||
private readonly IDictionary<Provider, IRssBuilder> _builders;
|
||||
|
||||
public CompositeRssBuilder(IServiceProvider serviceProvider, IStorageService storageService) : base(storageService)
|
||||
{
|
||||
_youTubeBuilder = serviceProvider.CreateInstance<YouTubeRssBuilder>();
|
||||
_vimeoBuilder = serviceProvider.CreateInstance<VimeoRssBuilder>();
|
||||
// Find all RSS builders (all implementations of IRssBuilder), create instances and make dictionary for fast search by Provider type
|
||||
var buildTypes = serviceProvider.FindAllImplementationsOf<IRssBuilder>(Assembly.GetEntryAssembly()).Where(x => x != typeof(CompositeRssBuilder));
|
||||
var builders = buildTypes.Select(builderType => (IRssBuilder)serviceProvider.CreateInstance(builderType)).ToDictionary(builder => builder.Provider);
|
||||
|
||||
_builders = new ReadOnlyDictionary<Provider, IRssBuilder>(builders);
|
||||
}
|
||||
|
||||
public override Provider Provider
|
||||
@@ -26,14 +32,10 @@ namespace Podsync.Services.Builder
|
||||
|
||||
public override Task<Rss> Query(Uri baseUrl, string feedId, FeedMetadata feed)
|
||||
{
|
||||
if (feed.Provider == Provider.YouTube)
|
||||
IRssBuilder builder;
|
||||
if (_builders.TryGetValue(feed.Provider, out builder))
|
||||
{
|
||||
return _youTubeBuilder.Query(baseUrl, feedId, feed);
|
||||
}
|
||||
|
||||
if (feed.Provider == Provider.Vimeo)
|
||||
{
|
||||
return _vimeoBuilder.Query(baseUrl, feedId, feed);
|
||||
return builder.Query(baseUrl, feedId, feed);
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Not supported provider");
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Podsync.Services.Feed;
|
||||
using Podsync.Services.Links;
|
||||
using Podsync.Services.Storage;
|
||||
|
||||
namespace Podsync.Services.Builder
|
||||
{
|
||||
public interface IRssBuilder
|
||||
{
|
||||
Provider Provider { get; }
|
||||
|
||||
Task<Rss> Query(Uri baseUrl, string feedId);
|
||||
|
||||
Task<Rss> Query(Uri baseUrl, string feedId, FeedMetadata metadata);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Shared
|
||||
@@ -19,5 +22,52 @@ namespace Shared
|
||||
{
|
||||
return ActivatorUtilities.CreateInstance(serviceProvider, type);
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> FindAllImplementationsOf(this IServiceProvider serviceProvider, Type interfaceType, Assembly assembly)
|
||||
{
|
||||
if (!interfaceType.GetTypeInfo().IsInterface)
|
||||
{
|
||||
throw new ArgumentException("T should be an interface");
|
||||
}
|
||||
|
||||
return GetLoadableTypes(assembly).Where(type => IsAssignableFrom(interfaceType, type));
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> FindAllImplementationsOf<T>(this IServiceProvider serviceProvider, Assembly assembly)
|
||||
{
|
||||
return serviceProvider.FindAllImplementationsOf(typeof(T), assembly);
|
||||
}
|
||||
|
||||
private static bool IsAssignableFrom(Type interfaceType, Type serviceType)
|
||||
{
|
||||
var serviceTypeInfo = serviceType.GetTypeInfo();
|
||||
if (serviceTypeInfo.IsInterface || serviceTypeInfo.IsAbstract)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var interfaceTypeInfo = interfaceType.GetTypeInfo();
|
||||
if (!interfaceTypeInfo.IsGenericType)
|
||||
{
|
||||
return interfaceType.IsAssignableFrom(serviceType);
|
||||
}
|
||||
|
||||
return serviceType
|
||||
.GetInterfaces()
|
||||
.Where(type => type.GetTypeInfo().IsGenericType)
|
||||
.Any(type => type.GetGenericTypeDefinition() == interfaceType);
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException e)
|
||||
{
|
||||
return e.Types.Where(x => x != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user