internal static Type ResolveGenerics()

in src/Microsoft.Azure.WebJobs.Host/Bindings/PatternMatcher.cs [207:270]


        internal static Type ResolveGenerics(Type type, Dictionary<string, Type> genericArgs)
        {
            // A generic type definition is an actual class / interface declaration, 
            // not to be confused with a signature referenced by the definition. 
            // Here, Foo'1 is the generic type definition, with one generic parameter, named 'T'
            // IEnumerable<T> is a type signature that containes a generic parameter. 
            // T is the generic parameter. 
            //    class Foo<T> : IEnumerable<T>
            //
            // MakeGenericType can only be called on a GenericTypeDefinition. 
            if (type.IsGenericTypeDefinition)
            {
                var typeArgs = type.GetGenericArguments();
                int len = typeArgs.Length;
                var actualTypeArgs = new Type[len];
                for (int i = 0; i < len; i++)
                {
                    actualTypeArgs[i] = genericArgs[typeArgs[i].Name];
                }

                var resolvedType = type.MakeGenericType(actualTypeArgs);

                return resolvedType;
            }
            else
            {
                // Simple case: T
                if (type.IsGenericParameter)
                {
                    var actual = genericArgs[type.Name];
                    return actual;
                }
                else if (type.ContainsGenericParameters)
                {                    
                    if (type.IsArray)
                    {
                        // T[] 
                        var elementType = type.GetElementType();
                        var resolved = ResolveGenerics(elementType, genericArgs);
                        return resolved.MakeArrayType();
                    }
                    // eg, IEnumerable<T>, IConverter<int, T>
                    // Must decompose to the generic definition, resolve each arg, and build back up. 

                    // potentially recursive case: ie, IConverter<int, T>
                    var def = type.GetGenericTypeDefinition();
                    var args = type.GetGenericArguments();

                    var resolvedArgs = new Type[args.Length];
                    for (int i = 0; i < args.Length; i++)
                    {
                        resolvedArgs[i] = ResolveGenerics(args[i], genericArgs);
                    }

                    var finalType = def.MakeGenericType(resolvedArgs);
                    return finalType;
                }
                else
                {
                    // Easy non-generic case. ie: string, int 
                    return type;
                }
            }
        }