Make TypeLoader generic loader

This commit is contained in:
ghorsington committed 2019-06-16 18:48:15 +03:00
1 parent e1f7382d97
commit a89ae05e40
3 files changed
+67 -61

No files matched your search

+41 -3
View File
@@ -79,6 +79,44 @@ namespace BepInEx.Bootstrap
_initialized = true;
}
private static PluginInfo ToPluginInfo(TypeDefinition type)
{
if (type.IsInterface || type.IsAbstract || !type.IsSubtypeOf(typeof(BaseUnityPlugin)))
return null;
var metadata = BepInPlugin.FromCecilType(type);
if (metadata == null)
{
Logger.LogWarning($"Skipping over type [{type.Name}] as no metadata attribute is specified");
return null;
}
//Perform a filter for currently running process
var filters = BepInProcess.FromCecilType(type);
bool invalidProcessName = filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == Paths.ProcessName);
if (invalidProcessName)
{
Logger.LogWarning($"Skipping over plugin [{metadata.GUID}] due to process filter");
return null;
}
var dependencies = BepInDependency.FromCecilType(type);
Logger.LogInfo($"Type path: {type.Module.FileName}");
return new PluginInfo
{
Metadata = metadata,
Processes = filters,
Dependencies = dependencies,
CecilType = type,
Location = type.Module.FileName
};
}
/// <summary>
/// The entrypoint for the BepInEx plugin system.
/// </summary>
@@ -108,7 +146,7 @@ namespace BepInEx.Bootstrap
UnityEngine.Object.DontDestroyOnLoad(ManagerObject);
var pluginsToLoad = TypeLoader.FindPluginTypes(Paths.PluginPath);
var pluginsToLoad = TypeLoader.FindPluginTypes(Paths.PluginPath, ToPluginInfo);
var pluginInfos = pluginsToLoad.SelectMany(p => p.Value).ToList();
@@ -184,8 +222,8 @@ namespace BepInEx.Bootstrap
if (missingDependencies.Count != 0)
{
Logger.LogError($@"Missing the following dependencies for [{pluginInfo.Metadata.Name}]: {"\r\n"}{
string.Join("\r\n", missingDependencies.Select(s => $"- {s}").ToArray())
}{"\r\n"}Loading will be skipped; expect further errors and unstabilities.");
string.Join("\r\n", missingDependencies.Select(s => $"- {s}").ToArray())
}{"\r\n"}Loading will be skipped; expect further errors and unstabilities.");
invalidPlugins.Add(pluginGUID);
continue;
+10 -49
View File
@@ -16,13 +16,6 @@ namespace BepInEx.Bootstrap
/// </summary>
public static class TypeLoader
{
private static bool Is(this TypeDefinition self, Type td)
{
if (self.FullName == td.FullName)
return true;
return self.FullName != "System.Object" && (self.BaseType?.Resolve().Is(td) ?? false);
}
private static DefaultAssemblyResolver resolver;
private static ReaderParameters readerParameters;
@@ -35,7 +28,9 @@ namespace BepInEx.Bootstrap
{
var name = new AssemblyName(reference.FullName);
if (Utility.TryResolveDllAssembly(name, Paths.BepInExAssemblyDirectory, readerParameters, out AssemblyDefinition assembly) || Utility.TryResolveDllAssembly(name, Paths.PluginPath, readerParameters, out assembly) || Utility.TryResolveDllAssembly(name, Paths.ManagedPath, readerParameters, out assembly))
if (Utility.TryResolveDllAssembly(name, Paths.BepInExAssemblyDirectory, readerParameters, out AssemblyDefinition assembly) ||
Utility.TryResolveDllAssembly(name, Paths.PluginPath, readerParameters, out assembly) ||
Utility.TryResolveDllAssembly(name, Paths.ManagedPath, readerParameters, out assembly))
return assembly;
return null;
@@ -48,11 +43,9 @@ namespace BepInEx.Bootstrap
/// <typeparam name="T">The specific base type to search for.</typeparam>
/// <param name="directory">The directory to search for assemblies.</param>
/// <returns>Returns a list of found derivative types.</returns>
public static Dictionary<AssemblyDefinition, IEnumerable<PluginInfo>> FindPluginTypes(string directory)
public static Dictionary<AssemblyDefinition, IEnumerable<T>> FindPluginTypes<T>(string directory, Func<TypeDefinition, T> typeSelector) where T : class
{
var result = new Dictionary<AssemblyDefinition, IEnumerable<PluginInfo>>();
var pluginType = typeof(BaseUnityPlugin);
string currentProcess = Process.GetCurrentProcess().ProcessName.ToLower();
var result = new Dictionary<AssemblyDefinition, IEnumerable<T>>();
foreach (string dll in Directory.GetFiles(Path.GetFullPath(directory), "*.dll", SearchOption.AllDirectories))
{
@@ -60,47 +53,15 @@ namespace BepInEx.Bootstrap
{
var ass = AssemblyDefinition.ReadAssembly(dll, readerParameters);
var matchingTypes = ass.MainModule.Types.Where(t => !t.IsInterface && !t.IsAbstract && t.Is(pluginType)).ToList();
var matches = ass.MainModule.Types.Select(typeSelector).Where(t => t != null).ToList();
if (matchingTypes.Count == 0)
continue;
var pluginInfos = new List<PluginInfo>();
foreach (var pluginTypeDefinition in matchingTypes)
if (matches.Count == 0)
{
var metadata = BepInPlugin.FromCecilType(pluginTypeDefinition);
if (metadata == null)
{
Logger.LogWarning($"Skipping over type [{pluginTypeDefinition.Name}] as no metadata attribute is specified");
continue;
}
//Perform a filter for currently running process
var filters = BepInProcess.FromCecilType(pluginTypeDefinition);
bool invalidProcessName = filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == currentProcess);
if (invalidProcessName)
{
Logger.LogInfo($"Skipping over plugin [{metadata.GUID}] due to process filter");
continue;
}
var dependencies = BepInDependency.FromCecilType(pluginTypeDefinition);
pluginInfos.Add(new PluginInfo
{
Metadata = metadata,
Processes = filters,
Dependencies = dependencies,
CecilType = pluginTypeDefinition,
Location = dll
});
ass.Dispose();
continue;
}
result[ass] = pluginInfos;
result[ass] = matches;
}
catch (Exception e)
{
+16 -9
View File
@@ -25,7 +25,7 @@ namespace BepInEx
/// <param name="input">The string to parse</param>
/// <param name="defaultValue">The value to return if parsing is unsuccessful.</param>
/// <returns>Boolean value of input if able to be parsed, otherwise default value.</returns>
public static bool SafeParseBool(string input, bool defaultValue = false) { return bool.TryParse(input, out bool result) ? result : defaultValue; }
public static bool SafeParseBool(string input, bool defaultValue = false) { return Boolean.TryParse(input, out bool result) ? result : defaultValue; }
/// <summary>
/// Converts a file path into a UnityEngine.WWW format.
@@ -39,7 +39,7 @@ namespace BepInEx
/// </summary>
/// <param name="self">The string to test.</param>
/// <returns>True if the value parameter is null or empty, or if value consists exclusively of white-space characters.</returns>
public static bool IsNullOrWhiteSpace(this string self) { return self == null || self.All(char.IsWhiteSpace); }
public static bool IsNullOrWhiteSpace(this string self) { return self == null || self.All(Char.IsWhiteSpace); }
public static IEnumerable<TNode> TopologicalSort<TNode>(IEnumerable<TNode> nodes, Func<TNode, IEnumerable<TNode>> dependencySelector)
{
@@ -128,14 +128,21 @@ namespace BepInEx
return false;
}
public static bool IsSubtypeOf(this TypeDefinition self, Type td)
{
if (self.FullName == td.FullName)
return true;
return self.FullName != "System.Object" && (self.BaseType?.Resolve().IsSubtypeOf(td) ?? false);
}
/// <summary>
/// Try to resolve and load the given assembly DLL.
/// </summary>
/// <param name="assemblyName">Name of the assembly, of the type <see cref="AssemblyName" />.</param>
/// <param name="directory">Directory to search the assembly from.</param>
/// <param name="assembly">The loaded assembly.</param>
/// <returns>True, if the assembly was found and loaded. Otherwise, false.</returns>
public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, Assembly.LoadFile, out assembly); }
/// Try to resolve and load the given assembly DLL.
/// </summary>
/// <param name="assemblyName">Name of the assembly, of the type <see cref="AssemblyName" />.</param>
/// <param name="directory">Directory to search the assembly from.</param>
/// <param name="assembly">The loaded assembly.</param>
/// <returns>True, if the assembly was found and loaded. Otherwise, false.</returns>
public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, Assembly.LoadFile, out assembly); }
/// <summary>
/// Try to resolve and load the given assembly DLL.