使用 Mono.Cecil 解析泛型
Resolve generics with Mono.Cecil
我有一个未知深度类型的层次结构。但是,这个层次结构实现了 IPlugin<T>
或 IPlugin<T1, T2>
接口(来自另一个 .dll
)。我如何解析来自 IPlugin
的 <T>
或 <T1, T2>
泛型?这个泛型位置可以随意在上面class.
示例:
// other .dll
interface IPlugin<T> {}
interface IPlugin<T1, T2> {}
// my code
class PluginBase<T1, T2>: IPlugin<T2, T1> {}
class AnotherClass<T1, T2, T3>: PluginBase<T3, T1> {}
class Plugin: AnotherClass<string, int, char> {}
从这个例子中我期望 string
和 char
类型定义。
Here is an example,但它使用的是参数的位置,没有层次结构的遍历。
结果是这样的代码:
public class TypeWithSelfReference
{
public TypeWithSelfReference(TypeDefinition type, TypeReference reference)
{
Type = type;
Reference = reference;
}
public TypeDefinition Type { get; }
public TypeReference Reference { get; }
public void Deconstruct(out TypeDefinition type, out TypeReference derived)
{
type = Type;
derived = Reference;
}
}
public static List<TypeWithSelfReference> GetHierarchy(this TypeDefinition typeDefinition, Func<TypeDefinition, bool> breakCondition)
{
var hierarchy = new List<TypeWithSelfReference>();
foreach (var definition in typeDefinition.Traverse())
{
hierarchy.Add(new TypeWithSelfReference(definition, null));
if (breakCondition(definition))
break;
}
hierarchy.Reverse();
for (var i = 0; i < hierarchy.Count - 1; i++)
{
hierarchy[i] = new TypeWithSelfReference(hierarchy[i].Type, hierarchy[i + 1].Type.BaseType);
}
return hierarchy.Take(hierarchy.Count - 1).ToList();
}
private static TypeReference ResolveGenericParameter(IEnumerable<TypeWithSelfReference> hierarchy, GenericParameter parameter)
{
foreach (var (type, reference) in hierarchy)
{
foreach (var genericParameter in type.GenericParameters)
{
if (genericParameter != parameter)
continue;
var nextArgument = ((GenericInstanceType) reference).GenericArguments[genericParameter.Position];
if (!(nextArgument is GenericParameter nextParameter))
return nextArgument;
parameter = nextParameter;
break;
}
}
return null;
}
我有一个未知深度类型的层次结构。但是,这个层次结构实现了 IPlugin<T>
或 IPlugin<T1, T2>
接口(来自另一个 .dll
)。我如何解析来自 IPlugin
的 <T>
或 <T1, T2>
泛型?这个泛型位置可以随意在上面class.
示例:
// other .dll
interface IPlugin<T> {}
interface IPlugin<T1, T2> {}
// my code
class PluginBase<T1, T2>: IPlugin<T2, T1> {}
class AnotherClass<T1, T2, T3>: PluginBase<T3, T1> {}
class Plugin: AnotherClass<string, int, char> {}
从这个例子中我期望 string
和 char
类型定义。
Here is an example,但它使用的是参数的位置,没有层次结构的遍历。
结果是这样的代码:
public class TypeWithSelfReference
{
public TypeWithSelfReference(TypeDefinition type, TypeReference reference)
{
Type = type;
Reference = reference;
}
public TypeDefinition Type { get; }
public TypeReference Reference { get; }
public void Deconstruct(out TypeDefinition type, out TypeReference derived)
{
type = Type;
derived = Reference;
}
}
public static List<TypeWithSelfReference> GetHierarchy(this TypeDefinition typeDefinition, Func<TypeDefinition, bool> breakCondition)
{
var hierarchy = new List<TypeWithSelfReference>();
foreach (var definition in typeDefinition.Traverse())
{
hierarchy.Add(new TypeWithSelfReference(definition, null));
if (breakCondition(definition))
break;
}
hierarchy.Reverse();
for (var i = 0; i < hierarchy.Count - 1; i++)
{
hierarchy[i] = new TypeWithSelfReference(hierarchy[i].Type, hierarchy[i + 1].Type.BaseType);
}
return hierarchy.Take(hierarchy.Count - 1).ToList();
}
private static TypeReference ResolveGenericParameter(IEnumerable<TypeWithSelfReference> hierarchy, GenericParameter parameter)
{
foreach (var (type, reference) in hierarchy)
{
foreach (var genericParameter in type.GenericParameters)
{
if (genericParameter != parameter)
continue;
var nextArgument = ((GenericInstanceType) reference).GenericArguments[genericParameter.Position];
if (!(nextArgument is GenericParameter nextParameter))
return nextArgument;
parameter = nextParameter;
break;
}
}
return null;
}