CECIL获取实现通用接口的类的GenericArg的TypeRef(例如ICollection)

时间:2017-07-19 06:42:20

标签: c# .net mono.cecil

注意:注意,这是一个Mono.Cecil特定问题,而不是System.Reflection的问题。

探索Cecil.ModuleDefinition可以获取所有已实施TypeReference的列表。众所周知,其中一些类型将实现(可能是间接的)ICollection<some_type>问题

  1. 列出模块中实现的所有TypeReference(直接或间接)ICollection

  2. 给出一个TypeReference提取TypeReference对应于实施ICollection时使用的通用参数的TypeReference

  3. 当源TypeReference指向完全指定的类型(即类型已知完整)但不是完全定义的时,“cookie崩溃”类型(即没有“体现”类型的类或结构)。更简单的演示方法是尝试从// "probed" code class Foo { } class Baz { public List<Foo> boz { get; set; } } 开始解决原始问题,而Baz.boz恰好是字段或属性的类型:

    TypeArgument

    然后使用Cecil“探测代码”,试图解决

    的问题
      

    ICollection属性的元素类型是什么,使用typeof(Baz.boz)实现的class Program { static void Main(string[] args) { ModuleDefinition module = ModuleDefinition.ReadModule(@"Probed.exe"); module.ReadSymbols(); TypeDefinition bazClass = module.Types.FirstOrDefault(e => e.FullName.EndsWith("Baz") // don't care about namespace, there only 1 Baz ); // The 'property type' is the type of the GetMethod for the property TypeReference bozPropTypeRef = bazClass.Properties.FirstOrDefault(p => p.Name == "boz").GetMethod.ReturnType; // Let's try to resolve the TypeReference to a TypeDefinition // to be able to access the Interfaces TypeDefinition bozPropTypeDef = bozPropTypeRef.Resolve(); foreach(var iface in bozPropTypeDef.Interfaces) { Console.WriteLine("Full iface name {0}", iface.FullName); /// Big bada-boom! The TypeArgument of the generic interfaces /// is wiped out } } } 接口的Full iface name System.Collections.Generic.IList`1<T> Full iface name System.Collections.Generic.ICollection`1<T> Full iface name System.Collections.Generic.IEnumerable`1<T> Full iface name System.Collections.IEnumerable Full iface name System.Collections.IList Full iface name System.Collections.ICollection Full iface name System.Collections.Generic.IReadOnlyList`1<T> Full iface name System.Collections.Generic.IReadOnlyCollection`1<T> ?”:

    <Foo>

    探测应用的输出是:

    <T>

    没有return,只有def foo[N: Numeric](bar: N) = bar.asInstanceOf[Float] 无处可指。

1 个答案:

答案 0 :(得分:0)

回复有点晚,但供将来参考:

TypeDefinition 永远不会包含类型参数,而是包含一个类型参数的列表。

List<string> 在 Mono.Cecil 中表示为 GenericInstanceType,因此您可以使用如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;

namespace testgen
{
    class Program
    {
        static void Main(string[] args)
        {
            using var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
            var prop = a.MainModule.Types.Single(t => t.Name == "Program").Properties.Single(p => p.Name == "Prop");

            var propType = (GenericInstanceType) prop.PropertyType;
            System.Console.WriteLine(propType.GenericArguments[0].FullName);
        }

        List<string> Prop {get; set; }
    }
}