diff --git a/IPA.Loader/Loader/PluginInitInjector.cs b/IPA.Loader/Loader/PluginInitInjector.cs
index 552f815b..c3dda102 100644
--- a/IPA.Loader/Loader/PluginInitInjector.cs
+++ b/IPA.Loader/Loader/PluginInitInjector.cs
@@ -33,17 +33,42 @@ namespace IPA.Loader
/// the function to call for injection.
public static void AddInjector(Type type, InjectParameter injector)
{
- injectors.Add(Tuple.Create(type, injector));
+ injectors.Add(new TypedInjector(type, injector));
}
- private static readonly List> injectors = new List>
+ private struct TypedInjector : IEquatable
{
- new Tuple(typeof(Logger), (prev, param, meta) => prev ?? new StandardLogger(meta.Name)),
+ public Type Type;
+ public InjectParameter Injector;
+
+ public TypedInjector(Type t, InjectParameter i)
+ { Type = t; Injector = i; }
+
+ public object Inject(object prev, ParameterInfo info, PluginLoader.PluginMetadata meta)
+ => Injector(prev, info, meta);
+
+ public bool Equals(TypedInjector other)
+ => Type == other.Type && Injector == other.Injector;
+
+ public override bool Equals(object obj)
+ => obj is TypedInjector i && Equals(i);
+
+
+ public override int GetHashCode()
+ => Type.GetHashCode() ^ Injector.GetHashCode();
+
+ public static bool operator ==(TypedInjector a, TypedInjector b) => a.Equals(b);
+ public static bool operator !=(TypedInjector a, TypedInjector b) => !a.Equals(b);
+ }
+
+ private static readonly List injectors = new List
+ {
+ new TypedInjector(typeof(Logger), (prev, param, meta) => prev ?? new StandardLogger(meta.Name)),
#pragma warning disable CS0618 // Type or member is obsolete
- new Tuple(typeof(IModPrefs), (prev, param, meta) => prev ?? new ModPrefs(meta)),
+ new TypedInjector(typeof(IModPrefs), (prev, param, meta) => prev ?? new ModPrefs(meta)),
#pragma warning restore CS0618 // Type or member is obsolete
- new Tuple(typeof(PluginLoader.PluginMetadata), (prev, param, meta) => prev ?? meta),
- new Tuple(typeof(IConfigProvider), (prev, param, meta) =>
+ new TypedInjector(typeof(PluginLoader.PluginMetadata), (prev, param, meta) => prev ?? meta),
+ new TypedInjector(typeof(IConfigProvider), (prev, param, meta) =>
{
if (prev != null) return prev;
var cfgProvider = Config.Config.GetProviderFor(meta.Name, param);
@@ -52,6 +77,28 @@ namespace IPA.Loader
})
};
+ private static int? MatchPriority(Type target, Type source)
+ {
+ if (target == source) return int.MaxValue;
+ if (!target.IsAssignableFrom(source)) return null;
+ if (!target.IsInterface && !source.IsSubclassOf(target)) return int.MinValue;
+
+ int value = 0;
+ while (true)
+ {
+ if (source == null) return value;
+ if (target.IsInterface && source.GetInterfaces().Contains(target))
+ return value;
+ else if (target == source)
+ return value;
+ else
+ {
+ value--; // lower priority
+ source = source.BaseType;
+ }
+ }
+ }
+
internal static void Inject(MethodInfo init, PluginLoader.PluginInfo info)
{
var instance = info.Plugin;
@@ -60,21 +107,28 @@ namespace IPA.Loader
var initArgs = new List