135 lines
4.7 KiB
C#
135 lines
4.7 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.Loader;
|
|
using Oqtane.Modules;
|
|
using Oqtane.Services;
|
|
using Oqtane.Shared;
|
|
using Oqtane.Themes;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace System.Reflection
|
|
{
|
|
public static class AssemblyExtensions
|
|
{
|
|
public static IEnumerable<Type> GetInterfaces<TInterfaceType>(this Assembly assembly)
|
|
{
|
|
if (assembly is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(assembly));
|
|
}
|
|
|
|
return assembly.GetTypes(typeof(TInterfaceType));
|
|
}
|
|
|
|
public static IEnumerable<Type> GetTypes(this Assembly assembly, Type interfaceType)
|
|
{
|
|
if (assembly is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(assembly));
|
|
}
|
|
|
|
if (interfaceType is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(interfaceType));
|
|
}
|
|
|
|
return assembly.GetTypes()
|
|
.Where(x => !x.IsInterface && !x.IsAbstract && interfaceType.IsAssignableFrom(x));
|
|
}
|
|
|
|
public static IEnumerable<Type> GetTypes<T>(this Assembly assembly)
|
|
{
|
|
return assembly.GetTypes(typeof(T));
|
|
}
|
|
|
|
public static IEnumerable<T> GetInstances<T>(this Assembly assembly) where T : class
|
|
{
|
|
if (assembly is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(assembly));
|
|
}
|
|
var type = typeof(T);
|
|
var list = assembly.GetTypes()
|
|
.Where(x => !x.IsInterface && !x.IsAbstract && !x.IsGenericType && type.IsAssignableFrom(x));
|
|
|
|
foreach (var type1 in list)
|
|
{
|
|
if (Activator.CreateInstance(type1) is T instance) yield return instance;
|
|
}
|
|
}
|
|
|
|
public static bool IsOqtaneAssembly(this Assembly assembly)
|
|
{
|
|
return assembly.FullName != null && (assembly.FullName.Contains("oqtane", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
public static bool IsOqtaneAssembly(this FileInfo fileInfo)
|
|
{
|
|
return (fileInfo.Name.Contains("oqtane", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
public static IEnumerable<Assembly> GetOqtaneAssemblies(this AppDomain appDomain)
|
|
{
|
|
return appDomain.GetAssemblies().Where(a => a.IsOqtaneAssembly());
|
|
}
|
|
|
|
public static IEnumerable<Assembly> GetOqtaneClientAssemblies(this AppDomain appDomain)
|
|
{
|
|
return appDomain.GetOqtaneAssemblies()
|
|
.Where(a => a.GetTypes<IModuleControl>().Any() || a.GetTypes<IThemeControl>().Any() || a.GetTypes<IClientStartup>().Any())
|
|
.Where(a => Utilities.GetFullTypeName(a.GetName().Name) != Constants.ClientId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if type should be ignored by oqtane dynamic loader
|
|
/// </summary>
|
|
/// <param name="type">Checked type</param>
|
|
/// <returns></returns>
|
|
public static bool IsOqtaneIgnore(this Type type)
|
|
{
|
|
return Attribute.IsDefined(type, typeof(OqtaneIgnoreAttribute)) || type.IsAbstract || type.IsGenericType;
|
|
}
|
|
|
|
public static void LoadOqtaneAssembly(this AssemblyLoadContext loadContext, FileInfo dll)
|
|
{
|
|
AssemblyName assemblyName = null;
|
|
try
|
|
{
|
|
assemblyName = AssemblyName.GetAssemblyName(dll.FullName);
|
|
}
|
|
catch
|
|
{
|
|
Debug.WriteLine($"Oqtane Error: Cannot Get Assembly Name For {dll.Name}");
|
|
}
|
|
|
|
loadContext.LoadOqtaneAssembly(dll, assemblyName);
|
|
}
|
|
|
|
public static void LoadOqtaneAssembly(this AssemblyLoadContext loadContext, FileInfo dll, AssemblyName assemblyName)
|
|
{
|
|
try
|
|
{
|
|
var pdb = Path.ChangeExtension(dll.FullName, ".pdb");
|
|
Assembly assembly = null;
|
|
|
|
// load assembly ( and symbols ) from stream to prevent locking files ( as long as dependencies are in /bin they will load as well )
|
|
if (File.Exists(pdb))
|
|
{
|
|
assembly = loadContext.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName)), new MemoryStream(File.ReadAllBytes(pdb)));
|
|
}
|
|
else
|
|
{
|
|
assembly = loadContext.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName)));
|
|
}
|
|
Debug.WriteLine($"Oqtane Info: Loaded Assembly {assemblyName}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine($"Oqtane Error: Unable To Load Assembly {assemblyName} - {ex}");
|
|
}
|
|
}
|
|
}
|
|
}
|