三国卡牌客户端基础资源仓库
yyl
23 小时以前 1566a91aadaaccad72c140dbcd38dd17dc0e5c0a
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 dnlib.DotNet;
using HybridCLR.Editor.ABI;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace HybridCLR.Editor.Meta
{
    public class MethodReferenceAnalyzer
    {
        private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;
 
        private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
 
        public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
        {
            _onNewMethod = onNewMethod;
        }
 
        public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
        {
            var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
 
            if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
            {
                foreach (var met in effectInsts)
                {
                    var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
                    _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
                }
                return;
            }
 
            var body = method.Body;
            if (body == null || !body.HasInstructions)
            {
                return;
            }
 
            effectInsts = new List<IMethod>();
            foreach (var inst in body.Instructions)
            {
                if (inst.Operand == null)
                {
                    continue;
                }
                switch (inst.Operand)
                {
                    case IMethod met:
                    {
                        if (!met.IsMethod)
                        {
                            continue;
                        }
                        var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
                        if (resolveMet == null)
                        {
                            continue;
                        }
                        effectInsts.Add(met);
                        _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
                        break;
                    }
                    case ITokenOperand token:
                    {
                        //GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ?
                        //            new GenericParamContext(method.DeclaringType, method) : default;
                        //method.Module.ResolveToken(token.MDToken, paramContext);
                        break;
                    }
                }
            }
            _methodEffectInsts.TryAdd(method, effectInsts);
        }
    }
}