using System; using System.IO; using System.Reflection; namespace IPA.Loader.Features { internal class InitInjectorFeature : Feature { protected internal override bool StoreOnPlugin => false; public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { // parameters should be (assembly qualified lookup type, [fully qualified type]:[method name]) // method should be static if (parameters.Length != 2) { InvalidMessage = "Incorrect number of parameters"; return false; } RequireLoaded(meta); var methodParts = parameters[1].Split(':'); var type = Type.GetType(parameters[0], false); if (type == null) { InvalidMessage = $"Could not find type {parameters[0]}"; return false; } Type getType; try { getType = meta.Assembly.GetType(methodParts[0]); } catch (ArgumentException) { InvalidMessage = $"Invalid type name {methodParts[0]}"; return false; } catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException) { string filename; switch (e) { case FileNotFoundException fn: filename = fn.FileName; goto hasFilename; case FileLoadException fl: filename = fl.FileName; goto hasFilename; case BadImageFormatException bi: filename = bi.FileName; hasFilename: InvalidMessage = $"Could not find {filename} while loading type"; break; default: InvalidMessage = $"Error while loading type: {e}"; break; } return false; } MethodInfo method; try { method = getType.GetMethod(methodParts[1], BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { typeof(object), typeof(ParameterInfo), typeof(PluginLoader.PluginMetadata) }, new ParameterModifier[0]); } catch (Exception e) { InvalidMessage = $"Error while loading type: {e}"; return false; } if (method == null) { InvalidMessage = $"Could not find method {methodParts[1]} in type {methodParts[0]}"; return false; } try { var del = (PluginInitInjector.InjectParameter)Delegate.CreateDelegate(typeof(PluginInitInjector.InjectParameter), null, method); PluginInitInjector.AddInjector(type, del); return true; } catch (Exception e) { InvalidMessage = $"Error generated while creating delegate: {e}"; return false; } } } }