从堆栈中的类获取泛型参数

本文关键字:获取 泛型 参数 堆栈 | 更新日期: 2023-09-27 17:58:40

我有一个名为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,而不是正确的类型,例如"User"或"Employee"。我无法比较类型的名称,因为t没有名称。

从堆栈中的类获取泛型参数

正如发布的评论所暗示的那样,使用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();
        }

不要认为这是可能的,因为你只得到了GenericType,而没有得到类的真正GenericArguments。

如果你看帧的返回。你会注意到,调试结果中只有GenericType,而不是真正的GenericArguments。

尝试这个

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