Files
Il2CppInspectorRedux/Il2CppInspector.Common/Reflection/MethodInfo.cs
Robert Xiao 652d76d6fe Implement constructors & methods on constructed generics.
We adopt roughly the same approach as the C# Reflection API: a
GenericMethodDefinition is a method which has no method parameters
substituted, but lives in a open or closed type with some or all
type parameters substituted. To ensure the uniqueness of the MethodInfo,
we cache by the method type arguments, and also cache generated
DeclaredConstructors/DeclaredMethods in the TypeInfo.

This also enables MakeGenericMethod, albeit in a slightly different form
than the Reflection API: MakeGenericMethod lives in MethodBase, so it's
callable from a constructor (even though in C# constructors cannot be
generic). This slight violation of the spec reduces code duplication, so
it's probably worth it.

Finally, VirtualAddress gets set when populating GenericMethods, and so
it'll work whether or not the methods get cached/generated ahead of
time.
2020-06-20 10:17:48 +02:00

49 lines
2.2 KiB
C#

/*
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
All rights reserved.
*/
using System.Linq;
using System.Reflection;
namespace Il2CppInspector.Reflection
{
public class MethodInfo : MethodBase
{
public override MemberTypes MemberType => MemberTypes.Method;
// Info about the return parameter
public ParameterInfo ReturnParameter { get; }
// Return type of the method
public TypeInfo ReturnType => ReturnParameter.ParameterType;
public override bool RequiresUnsafeContext => base.RequiresUnsafeContext || ReturnType.RequiresUnsafeContext;
// IL2CPP doesn't seem to retain return type custom attributes
public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) {
// Add return parameter
ReturnParameter = new ParameterInfo(pkg, -1, this);
}
public MethodInfo(MethodInfo methodDef, TypeInfo declaringType) : base(methodDef, declaringType) {
ReturnParameter = ((MethodInfo)rootDefinition).ReturnParameter
.SubstituteGenericArguments(this, DeclaringType.GetGenericArguments(), GetGenericArguments());
}
private MethodInfo(MethodInfo methodDef, TypeInfo[] typeArguments) : base(methodDef, typeArguments) {
ReturnParameter = ((MethodInfo)rootDefinition).ReturnParameter
.SubstituteGenericArguments(this, DeclaringType.GetGenericArguments(), GetGenericArguments());
}
protected override MethodBase MakeGenericMethodImpl(TypeInfo[] typeArguments) => new MethodInfo(this, typeArguments);
public override string ToString() => ReturnType.Name + " " + Name + GetFullTypeParametersString() + "(" + string.Join(", ",
DeclaredParameters.Select(x => x.ParameterType.IsByRef? x.ParameterType.Name.TrimEnd('&') + " ByRef" : x.ParameterType.Name)) + ")";
public override string GetSignatureString() => ReturnParameter.GetSignatureString() + " " + Name + GetFullTypeParametersString()
+ "(" + string.Join(",", DeclaredParameters.Select(x => x.GetSignatureString())) + ")";
}
}