注意:注意,这是一个Mono.Cecil
特定问题,而不是System.Reflection
的问题。
探索Cecil.ModuleDefinition
可以获取所有已实施TypeReference
的列表。众所周知,其中一些类型将实现(可能是间接的)ICollection<some_type>
。问题:
列出模块中实现的所有TypeReference
(直接或间接)ICollection
给出一个TypeReference
提取TypeReference
对应于实施ICollection
时使用的通用参数的TypeReference
。
当源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]
无处可指。
答案 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; }
}
}