forked from InscryptionModding/InscryptionAPI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTypeMapper.cs
More file actions
79 lines (73 loc) · 2.98 KB
/
TypeMapper.cs
File metadata and controls
79 lines (73 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
using Mono.Cecil.Cil;
using MonoMod.Utils;
namespace APIPlugin
{
[AttributeUsage(AttributeTargets.Field)]
public class IgnoreMappingAttribute : Attribute {}
public static class TypeMapper<S, D> where S : class where D : class
{
private static Dictionary<string, MethodInfo> _accessors = null;
private static Dictionary<string, MethodInfo> FieldAccessors
{
get
{
if (_accessors is null)
{
_accessors = new();
foreach (var field in AccessTools.GetDeclaredFields(typeof(S)).Where(x => !x.GetCustomAttributes(typeof(IgnoreMappingAttribute), false).Any()))
{
var accessor = new DynamicMethodDefinition("get_" + field.Name, typeof(object), new Type[] { typeof(S) });
var il = accessor.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, accessor.Module.ImportReference(field));
if (field.FieldType.IsValueType)
il.Emit(OpCodes.Box, field.FieldType);
il.Emit(OpCodes.Ret);
_accessors.Add(field.Name, accessor.Generate());
}
}
return _accessors;
}
}
private static Dictionary<string, MethodInfo> _setters = null;
private static Dictionary<string, MethodInfo> FieldSetters
{
get
{
if (_setters == null)
{
_setters = new();
foreach (var field in AccessTools.GetDeclaredFields(typeof(D)))
{
var setter = new DynamicMethodDefinition("set_" + field.Name, typeof(void), new Type[] { typeof(D), typeof(object) });
var il = setter.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Unbox_Any, setter.Module.ImportReference(field.FieldType));
il.Emit(OpCodes.Stfld, setter.Module.ImportReference(field));
il.Emit(OpCodes.Ret);
_setters.Add(field.Name, setter.Generate());
}
}
return _setters;
}
}
public static D Convert(S source, D destination)
{
foreach (var field in FieldAccessors)
{
object val = field.Value.Invoke(null, new object[] {source});
if (val is not null && FieldSetters.ContainsKey(field.Key))
{
FieldSetters[field.Key].Invoke(null, new object[] {destination, val});
}
}
return destination;
}
}
}