Получение общих аргументов из класса в стеке - PullRequest
3 голосов
/ 06 июня 2011

У меня есть универсальный класс, который называется Repository. Этот класс имеет функцию, которая «вызывает себя», инициализируя новый экземпляр класса Repository с другим универсальным аргументом. Эта «рекурсия» может продолжаться - поэтому, чтобы избежать StackOverflowException, мне нужно проверить, есть ли в стеке метод, вызванный из класса Repository с тем же универсальным аргументом. вот мой код:

    StackTrace stack = new StackTrace();
    StackFrame[] frames = stack.GetFrames();

    foreach (StackFrame frame in frames)
    {
        Type callingMethodClassType = frame.GetMethod().DeclaringType;
        if (callingMethodClassType.IsGenericType)
        {
            // BUG HERE in getting generic arguments of the class in stack
            Type genericType = callingMethodClassType.GetGenericArguments()[0];
            if (genericType.Equals(entityType))
            {
                wasAlready = true;
                break;
            }
        }
    }

универсальный тип всегда возвращается как T, а не правильный тип, например «Пользователь» или «Сотрудник» (например). Я не могу сравнить имена типов, потому что у T нет имени.

Ответы [ 3 ]

2 голосов
/ 06 июня 2011

Поскольку опубликованный комментарий предлагает использовать StackFrame, он немного сложен и подвержен ошибкам. Также я не уверен, что вы сможете получить информацию о закрытом типе универсального типа.

Но вы могли бы следовать другому подходу, при котором вы сохраняете List<Type>, который уже был обработан. Ниже приведены две версии метода CreateRepository, который, как я полагаю, используется вами для создания репозиториев элементов.

private static List<Type> addedItemList; has the info of all the created types so far.

Версия - 1

        public static Repository<T> CreateRepository(T item)
        {
            if (addedItemList.Contains<Type>(item.GetType()))
            {
                return new Repository<T> { Item = item };
            }

            addedItemList.Add(item.GetType());

            return CreateRepository(item);

        }

Версия 2

        public static Repository<T> CreateRepository()
        {
            if (addedItemList.Contains<Type>(typeof(T)))
            {
                return new Repository<T> { Item = default(T) };
            }

            addedItemList.Add(typeof(T));

            return CreateRepository();
        }
0 голосов
/ 06 июня 2011

Не думайте, что это возможно, потому что вы получаете только GenericType, но не настоящие GenericArguments класса.

Если вы посмотрите на возвращение frame.GetMethod (). DeclaringType, вы заметите, что в результате отладки находится только GenericType, но не реальные GenericArguments.

0 голосов
/ 06 июня 2011

попробуйте

StackTrace stack = new StackTrace();
StackFrame[] frames = stack.GetFrames();

foreach (StackFrame frame in frames)
{
    Type callingMethodClassType = frame.GetMethod().DeclaringType;
    if (callingMethodClassType.IsGenericType)
    {
        // BUG HERE in getting generic arguments of the class in stack
        Type genericType = callingMethodClassType.GetGenericArguments()[0];
        if (genericType.GetFullName.Equals(entityType.GetFullName))
        {
            wasAlready = true;
            break;
        }
    }
}

private static String GetFullName<T>(this T type) 
{
    return typeof(T).FullName;
}
...