using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using System.Reflection;
namespace zero.Architecture;
public class AssemblyDiscovery : IAssemblyDiscovery
{
public static IAssemblyDiscovery Current;
AssemblyDiscoveryContext Context;
IMvcBuilder Mvc;
public AssemblyDiscovery(IMvcBuilder mvc)
{
Mvc = mvc;
Context = new AssemblyDiscoveryContext();
Current = this;
}
///
public void Execute(IEnumerable rules)
{
List assemblies = new List();
DependencyContext dependencyContext = DependencyContext.Load(Context.EntryAssembly);
if (dependencyContext == null)
{
return;
}
string[] existingLibs = Mvc.PartManager.ApplicationParts.OfType().Select(p => p.Name).ToArray();
IEnumerable libraries = dependencyContext.RuntimeLibraries.Where(lib => !existingLibs.Contains(lib.Name, StringComparer.OrdinalIgnoreCase));
foreach (RuntimeLibrary library in libraries)
{
if (rules.Any(rule => rule.IsValid(library, Context)))
{
IEnumerable libraryAssemblies = library.GetDefaultAssemblyNames(dependencyContext).Select(name => Assembly.Load(name));
foreach (Assembly assembly in libraryAssemblies)
{
Mvc.AddApplicationPart(assembly);
}
}
}
}
///
public void AddAssembly(Assembly assembly)
{
string[] existingLibs = Mvc.PartManager.ApplicationParts.OfType().Select(p => p.Name).ToArray();
if (!existingLibs.Contains(assembly.GetName().Name))
{
Mvc.AddApplicationPart(assembly);
}
}
///
public IEnumerable GetTypes(bool allowGenerics = false) => GetTypes(typeof(TService), allowGenerics);
///
public IEnumerable GetTypes(IEnumerable parts, bool allowGenerics = false) => GetTypes(typeof(TService), parts, allowGenerics);
///
public IEnumerable GetTypes(Type serviceType, bool allowGenerics = false) => GetAllClassTypes(allowGenerics).Where(t => serviceType.GetTypeInfo().IsAssignableFrom(t) && t.AsType() != serviceType);
///
public IEnumerable GetTypes(Type serviceType, IEnumerable parts, bool allowGenerics = false) => GetAllClassTypes(parts, allowGenerics).Where(t => serviceType.GetTypeInfo().IsAssignableFrom(t) && t.AsType() != serviceType);
///
public IEnumerable GetAllClassTypes(bool allowGenerics = false) => GetAllTypes().Where(t => t.IsClass && !t.IsAbstract && (allowGenerics || !t.ContainsGenericParameters));
///
public IEnumerable GetAllClassTypes(IEnumerable parts, bool allowGenerics = false) => GetAllTypes(parts).Where(t => t.IsClass && !t.IsAbstract && (allowGenerics || !t.ContainsGenericParameters));
///
public IEnumerable GetAssemblies() => Mvc.PartManager.ApplicationParts.OfType().Select(p => p.Assembly);
///
public IEnumerable GetAssemblies(IEnumerable parts) => parts.OfType().Select(p => p.Assembly);
///
public IEnumerable GetAllTypes() => Mvc.PartManager.ApplicationParts.OfType().SelectMany(p => p.Types);
///
public IEnumerable GetAllTypes(IEnumerable parts) => parts.OfType().SelectMany(p => p.Types);
}
public interface IAssemblyDiscovery
{
///
/// Discovers runtime assemblies based on the given rules
///
void Execute(IEnumerable rules);
///
/// Manually add an assembly
///
void AddAssembly(Assembly assembly);
///
/// Get all discovered types which implement a certain service
///
IEnumerable GetTypes(bool allowGenerics = false);
///
/// Get all discovered types which implement a certain service
///
IEnumerable GetTypes(IEnumerable parts, bool allowGenerics = false);
///
/// Get all discovered types which implement a certain service
///
IEnumerable GetTypes(Type serviceType, bool allowGenerics = false);
///
/// Get all discovered types which implement a certain service
///
IEnumerable GetTypes(Type serviceType, IEnumerable parts, bool allowGenerics = false);
///
/// Get all registered types
///
IEnumerable GetAllTypes();
///
/// Get all registered types
///
IEnumerable GetAllTypes(IEnumerable parts);
///
/// Get all registered types
///
IEnumerable GetAllClassTypes(bool allowGenerics = false);
///
/// Get all registered types
///
IEnumerable GetAllClassTypes(IEnumerable parts, bool allowGenerics = false);
///
/// Get all registered assemblies
///
IEnumerable GetAssemblies();
///
/// Get all registered assemblies
///
IEnumerable GetAssemblies(IEnumerable parts);
}