Mono.Cecil: получить общее имя параметра

Мы кодируем проект, который проверяет, есть ли проблемы со ссылками в наших пакетах nuget. Поэтому мы решили использовать Mono.cecil для извлечения всех вызовов методов, а затем проверять, находим ли мы метод, который подходит для вызова.

При извлечении каждого вызова метода я получаю, например,

string fullName = !!0 Extensions::MinBy(System.Collections.Generic.IEnumerable`1<!!0>,System.Func`2<!!0,!!1>)

Где !!0 и !!1 являются универсальными аргументами для метода:

public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> selector)

Мне было интересно, есть ли способ получить вместо этого:

TSource Extensions::MinBy(System.Collections.Generic.IEnumerable`1<TSource>,System.Func`2<TSource, TKey>)
                AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(path);
                foreach (ModuleDefinition module in assembly.Modules)
                {
                    foreach (TypeDefinition type in module.Types)
                    {
                        foreach (MethodDefinition method in type.Methods.Where(x => x.HasBody))
                        {
                            foreach (var il in method.Body.Instructions)
                            {
                                if (il.OpCode == OpCodes.Call || il.OpCode == OpCodes.Calli || il.OpCode == OpCodes.Callvirt)
                                {
                                    var mRef = il.Operand as MethodReference;

                                    string fullName = mRef.GetElementMethod().FullName; // This is where i get !!0 Extensions::MinBy(System.Collections.Generic.IEnumerable`1<!!0>,System.Func`2<!!0,!!1>)

                                    **//TODO : Find a way to obtain parameters names**

                                }
                            }
                        }
                    }
                }

Большое спасибо


person Marc-André Brunelle-Langevin    schedule 10.12.2019    source источник


Ответы (1)


Я не уверен, что Mono.Cecil предоставляет эту функциональность. Похоже, что параметры типа, поступающие из объявляющего типа, используют имя параметра типа (вместо синтаксиса IL !0, !1 и т. д.).

При этом вы можете сделать что-то вроде (помните, что это просто для вдохновения):

var genMethod = mRef as GenericInstanceMethod;
if (genMethod != null)
{
    for(var i = 0 ; i < genMethod.GenericArguments.Count; i++)
        fullName = fullName.Replace($"!!{i}",  genMethod.GenericArguments[i].Name);
}
person Vagaus    schedule 11.12.2019