开发者

Getting generic arguments from a class in the stack

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

开发者_StackOverflow    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.


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


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.


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜