Получить generic аргументы с помощью Mono.Cecil

140
29 сентября 2019, 03:30

У меня есть иерархия типов произвольной глубины, которая в конце реализует IPlugin<T> или IPlugin<T1, T2> интерфейс, который находится в другой .dll. Нужно понять, какие типы попадут в <T> или <T1, T2>. Причём, позиция типов в изначальном классе (или любом другом по пути иерархии) может не соответствовать их позиции в интерфейсе.

Пример:

// 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.

Вот тут есть пример кода, но он использует позицию аргументов и не учитывает иерархию типов.

Answer 1

В итоге написал вот такой код:

        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;
        }
READ ALSO
Laravel Авторизация с ролями многие ко многим

Laravel Авторизация с ролями многие ко многим

пытаюсь сделать авторизацию на ларавел с двумя ролямиНе понимаю как проверить права пользователя

110
Ошибка в .htaccess

Ошибка в .htaccess

Выдает 500 ошибкуВ чем ошибка? Сам тут полный 0

141
Как на php и mysql избрранное вещей сделать? [закрыт]

Как на php и mysql избрранное вещей сделать? [закрыт]

я создал таблицы users, post и psusers - пользователь, post - почты, ps - хранятся id users и post

122