/// <summary>
        /// Binds a name to type.
        /// </summary>
        /// <param name="typeName">The name of the type to bind.</param>
        /// <param name="debugContext">The debug context to log to.</param>
        /// <returns>
        /// The type that the name has been bound to, or null if the type could not be resolved.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">The typeName argument is null.</exception>
        public override Type BindToType(string typeName, DebugContext debugContext = null)
        {
            if (typeName == null)
            {
                throw new ArgumentNullException("typeName");
            }

            RegisterAllQueuedAssembliesRepeating();

            Type result;

            lock (NAMETOTYPE_LOCK)
            {
                if (typeMap.TryGetValue(typeName, out result) == false)
                {
                    result = this.ParseTypeName(typeName, debugContext);

                    if (result == null && debugContext != null)
                    {
                        debugContext.LogWarning("Failed deserialization type lookup for type name '" + typeName + "'.");
                    }

                    // We allow null values on purpose so we don't have to keep re-performing invalid name lookups
                    typeMap.Add(typeName, result);
                }
            }

            return(result);
        }
        private Type ParseGenericAndOrArrayType(string typeName, DebugContext debugContext)
        {
            string        actualTypeName;
            List <string> genericArgNames;

            bool isGeneric;
            bool isArray;
            int  arrayRank;

            if (!TryParseGenericAndOrArrayTypeName(typeName, out actualTypeName, out isGeneric, out genericArgNames, out isArray, out arrayRank))
            {
                return(null);
            }

            Type type = this.BindToType(actualTypeName, debugContext);

            if (type == null)
            {
                return(null);
            }

            if (isGeneric)
            {
                if (!type.IsGenericType)
                {
                    return(null);
                }

                List <Type> args = genericArgTypesList;
                args.Clear();

                for (int i = 0; i < genericArgNames.Count; i++)
                {
                    Type arg = this.BindToType(genericArgNames[i], debugContext);
                    if (arg == null)
                    {
                        return(null);
                    }
                    args.Add(arg);
                }

                var argsArray = args.ToArray();

                if (!type.AreGenericConstraintsSatisfiedBy(argsArray))
                {
                    if (debugContext != null)
                    {
                        string argsStr = "";

                        foreach (var arg in args)
                        {
                            if (argsStr != "")
                            {
                                argsStr += ", ";
                            }
                            argsStr += arg.GetNiceFullName();
                        }

                        debugContext.LogWarning("Deserialization type lookup failure: The generic type arguments '" + argsStr + "' do not satisfy the generic constraints of generic type definition '" + type.GetNiceFullName() + "'. All this parsed from the full type name string: '" + typeName + "'");
                    }

                    return(null);
                }

                type = type.MakeGenericType(argsArray);
            }

            if (isArray)
            {
                type = type.MakeArrayType(arrayRank);
            }

            return(type);
        }