简体   繁体   中英

Mono.Cecil : Get generic parameter name

We are coding a project that check if there are references problems within our nuget packages. So we decided to use Mono.cecil to extract every method calls, and then check if we find a method that suits the call.

While extracting every method calls, I obtain for example

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

Where !!0 and !!1 are generics arguments for the method :

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

I was wondering if there was a way to obtain instead :

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**

                                }
                            }
                        }
                    }
                }

Thanks a lot

I am not sure if Mono.Cecil provides this functionality. It does appear that type parameters coming from the declaring type uses the type parameter name (instead of the IL syntax !0, !1, etc).

That being said, you can do something like (remember this is just for inspiration):

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM