I have a hierarchy of arbitrary depth types, which at the end implements the IPlugin<T> or IPlugin<T1, T2> interface, which is in a different .dll . You need to understand which types fall into <T> or <T1, T2> . Moreover, the position of types in the original class (or any other hierarchy along the way) may not correspond to their position in the interface.

Example:

 // 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> {} 

From this example, I expect to pull out string and char .

Here is a sample code , but it uses the position of the arguments and does not take into account the type hierarchy.

  • you have something wrong, describe in more detail why do you need it? - Monomax
  • @Monomax A script like this: I receive a set of .dll , one of which has a type that implements the IPlugin interface. My goal is to find out which generic user has “fired” into this interface. In runtime with this, there would be no problems, because there they would be closed at the interface itself, but with cecil you need to analyze the hierarchy. - CRRRRRRRRASH

1 answer 1

As a result, I wrote the following code:

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