Getting generic arguments from a class in the stack

怎甘沉沦 提交于 2019-12-10 15:58:10

问题


I have a generic class called Repository. This class has a function that "calls itself" by initializing a new instance of the Repository class with a different generic argument. This "recursion" can go on - so to avoid StackOverflowException, i need to check if there is in the stack, a method called from the Repository class with the same generic argument. here is my code:

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

the generic type always returns as T and not the correct type like "User" or "Employee" (for example). I can't compare the names of the types because T does not have a name.


回答1:


Don't think that this is possible, because you only get the GenericType, but not the real GenericArguments of the class.

If you look at the return of frame.GetMethod().DeclaringType you'll notice, that only the GenericType, but not the real GenericArguments are within the debugging result.




回答2:


As the posted comment suggest using StackFrame is bit tricky and error prone. Also I'm not sure if you would be able to get the info about the closed type of the generic type.

But you could follow another approach where in you maintain the List<Type> that have already been processed. Below are two versions of the method CreateRepository which I assume is the method that you might be using to create item repositories.

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

Version - 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);

        }

Version 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();
        }



回答3:


try this

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


来源:https://stackoverflow.com/questions/6250931/getting-generic-arguments-from-a-class-in-the-stack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!