SMAPI/ModLoader/MonoMod/Utils/ILExt.cs

133 lines
5.3 KiB
C#

using System;
using System.Reflection;
using MonoMod.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
#if NETSTANDARD
using TypeOrTypeInfo = System.Reflection.TypeInfo;
using static System.Reflection.IntrospectionExtensions;
using static System.Reflection.TypeExtensions;
#else
using TypeOrTypeInfo = System.Type;
#endif
namespace MonoMod.Utils {
public static class ILExt {
#region Misc Helpers
public static bool Is(this MemberReference member, string fullName) {
if (member == null)
return false;
return member.FullName.Replace("+", "/") == fullName.Replace("+", "/");
}
public static bool Is(this MemberReference member, string typeFullName, string name) {
if (member == null)
return false;
return member.DeclaringType.FullName.Replace("+", "/") == typeFullName.Replace("+", "/") && member.Name == name;
}
public static bool Is(this MemberReference member, Type type, string name) {
if (member == null)
return false;
return member.DeclaringType.FullName.Replace("+", "/") == type.FullName.Replace("+", "/") && member.Name == name;
}
#endregion
#region Misc IL Helpers
public static void ReplaceOperands(this ILProcessor il, object from, object to) {
foreach (Instruction instr in il.Body.Instructions)
if (instr.Operand?.Equals(from) ?? from == null)
instr.Operand = to;
}
#endregion
#region Base Create / Emit Helpers
public static FieldReference Import(this ILProcessor il, FieldInfo field)
=> il.Body.Method.Module.ImportReference(field);
public static MethodReference Import(this ILProcessor il, MethodBase method)
=> il.Body.Method.Module.ImportReference(method);
public static TypeReference Import(this ILProcessor il, Type type)
=> il.Body.Method.Module.ImportReference(type);
public static MemberReference Import(this ILProcessor il, MemberInfo member) {
if (member == null)
throw new ArgumentNullException(nameof(member));
switch (member) {
case FieldInfo info:
return il.Import(info);
case MethodBase info:
return il.Import(info);
case TypeOrTypeInfo info:
return il.Import(info.AsType());
default:
throw new NotSupportedException("Unsupported member type " + member.GetType().FullName);
}
}
public static Instruction Create(this ILProcessor il, OpCode opcode, FieldInfo field)
=> il.Create(opcode, il.Import(field));
public static Instruction Create(this ILProcessor il, OpCode opcode, MethodBase method) {
if (method is System.Reflection.Emit.DynamicMethod)
return il.Create(opcode, (object) method);
return il.Create(opcode, il.Import(method));
}
public static Instruction Create(this ILProcessor il, OpCode opcode, Type type)
=> il.Create(opcode, il.Import(type));
public static Instruction Create(this ILProcessor il, OpCode opcode, object operand) {
Instruction instr = il.Create(OpCodes.Nop);
instr.OpCode = opcode;
instr.Operand = operand;
return instr;
}
public static Instruction Create(this ILProcessor il, OpCode opcode, MemberInfo member) {
if (member == null)
throw new ArgumentNullException(nameof(member));
switch (member) {
case FieldInfo info:
return il.Create(opcode, info);
case MethodBase info:
return il.Create(opcode, info);
case TypeOrTypeInfo info:
return il.Create(opcode, info.AsType());
default:
throw new NotSupportedException("Unsupported member type " + member.GetType().FullName);
}
}
public static void Emit(this ILProcessor il, OpCode opcode, FieldInfo field)
=> il.Emit(opcode, il.Import(field));
public static void Emit(this ILProcessor il, OpCode opcode, MethodBase method)
=> il.Emit(opcode, il.Import(method));
public static void Emit(this ILProcessor il, OpCode opcode, Type type)
=> il.Emit(opcode, il.Import(type));
public static void Emit(this ILProcessor il, OpCode opcode, MemberInfo member) {
if (member == null)
throw new ArgumentNullException(nameof(member));
switch (member) {
case FieldInfo info:
il.Emit(opcode, info);
break;
case MethodBase info:
il.Emit(opcode, info);
break;
case TypeOrTypeInfo info:
il.Emit(opcode, info.AsType());
break;
default:
throw new NotSupportedException("Unsupported member type " + member.GetType().FullName);
}
}
public static void Emit(this ILProcessor il, OpCode opcode, object operand)
=> il.Append(il.Create(opcode, operand));
#endregion
}
}