From ad5fc04a3b305803a5e75febc715fc236748687b Mon Sep 17 00:00:00 2001
From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com>
Date: Sat, 19 Sep 2020 01:27:33 +1000
Subject: [PATCH] Fix methods with multiple generic constraints
---
src/CachedObjects/CacheObjectBase.cs | 26 +++++++++++++++++++++++---
src/CachedObjects/Other/CacheMethod.cs | 22 +++++++++++-----------
src/Tests/TestClass.cs | 11 ++++++++++-
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/CachedObjects/CacheObjectBase.cs b/src/CachedObjects/CacheObjectBase.cs
index 3847fd8..6c14faf 100644
--- a/src/CachedObjects/CacheObjectBase.cs
+++ b/src/CachedObjects/CacheObjectBase.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using MelonLoader;
using UnityEngine;
@@ -400,9 +401,28 @@ namespace Explorer
for (int i = 0; i < cm.GenericArgs.Length; i++)
{
- var type = cm.GenericConstraints[i]?.FullName ?? "Any";
+ string types = "";
+ if (cm.GenericConstraints[i].Length > 0)
+ {
+ foreach (var constraint in cm.GenericConstraints[i])
+ {
+ if (types != "") types += ", ";
+
+ string type;
+
+ if (constraint == null)
+ type = "Any";
+ else
+ type = constraint.ToString();
+
+ types += $"{type}";
+ }
+ }
+ else
+ {
+ types = $"Any";
+ }
var input = cm.GenericArgInput[i];
- var label = $"{type}";
GUILayout.BeginHorizontal(null);
@@ -410,7 +430,7 @@ namespace Explorer
GUILayout.Label($"{cm.GenericArgs[i].Name}", new GUILayoutOption[] { GUILayout.Width(15) });
cm.GenericArgInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
- GUILayout.Label(label, null);
+ GUILayout.Label(types, null);
GUILayout.EndHorizontal();
}
diff --git a/src/CachedObjects/Other/CacheMethod.cs b/src/CachedObjects/Other/CacheMethod.cs
index 47feb99..d25b9aa 100644
--- a/src/CachedObjects/Other/CacheMethod.cs
+++ b/src/CachedObjects/Other/CacheMethod.cs
@@ -14,7 +14,7 @@ namespace Explorer
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
public Type[] GenericArgs { get; private set; }
- public Type[] GenericConstraints { get; private set; }
+ public Type[][] GenericConstraints { get; private set; }
public string[] GenericArgInput = new string[0];
@@ -23,8 +23,7 @@ namespace Explorer
var mi = (MemInfo as MethodInfo);
GenericArgs = mi.GetGenericArguments();
- GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints()
- .FirstOrDefault())
+ GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
.ToArray();
GenericArgInput = new string[GenericArgs.Length];
@@ -86,21 +85,22 @@ namespace Explorer
var input = GenericArgInput[i];
if (ReflectionHelpers.GetTypeByName(input) is Type t)
{
- if (GenericConstraints[i] == null)
+ if (GenericConstraints[i].Length == 0)
{
list.Add(t);
}
else
{
- if (GenericConstraints[i].IsAssignableFrom(t))
+ foreach (var constraint in GenericConstraints[i].Where(x => x != null))
{
- list.Add(t);
- }
- else
- {
- MelonLogger.LogWarning($"Generic argument #{i} '{input}', is not assignable from the generic constraint!");
- return null;
+ if (!constraint.IsAssignableFrom(t))
+ {
+ MelonLogger.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
+ return null;
+ }
}
+
+ list.Add(t);
}
}
else
diff --git a/src/Tests/TestClass.cs b/src/Tests/TestClass.cs
index 5bd80eb..e06e693 100644
--- a/src/Tests/TestClass.cs
+++ b/src/Tests/TestClass.cs
@@ -3,6 +3,14 @@ using System.Collections.Generic;
using System;
using UnityEngine;
+// used to test multiple generic constraints
+public class TestGeneric : IComparable
+{
+ public TestGeneric() { }
+
+ public int CompareTo(string other) => throw new NotImplementedException();
+}
+
namespace Explorer.Tests
{
public class TestClass
@@ -22,7 +30,8 @@ namespace Explorer.Tests
public static int StaticField = 5;
public int NonStaticField;
- public static string TestGeneric(string arg0) where C : Component
+
+ public static string TestGeneric(string arg0) where C : Component where T : TestGeneric, IComparable
{
return $"C: '{typeof(C).FullName}', T: '{typeof(T).FullName}', arg0: '{arg0}'";
}