简体   繁体   中英

Resolve generics with Mono.Cecil

I have a hierarchy of types of unknown depth. But at the and, this hierarchy implements IPlugin<T> or IPlugin<T1, T2> interface (from the other .dll ). How can I resolve <T> or <T1, T2> generics from IPlugin ? This generics position can be random on the top class.

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 string and char type definition.

Here is an example , but it uses the position of the arguments and there is no traversal of the hierarchy.

The result is a code like this:

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

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