// Given a control's type, returns the adapter type to be used.
        // Note that it's legal to not register an adapter type for each
        // control type.
        //
        // This lookup uses the following steps:
        //
        // (1) Look up the control type directly, to see if an adapter type
        //     has been registered for it.
        // (2) Walk up the control inheritance chain, to see if an adapter type
        //     has been registered for the class. For example, if the passed
        //     control type is a validator, check BaseValidator, Label,
        //     TextControl, and finally MobileControl.
        // (3) If no adapter type has still been found, call the parent configuration,
        //     if any, to look up the adapter type. For example, the CHTML device
        //     configuration would call the HTML device configuration.
        // (4) If an adapter type is found, but is not explicitly registered for
        //     the passed control type, add an entry to the table, so that
        //     subsequent requests do not need to walk the hierarchy.

        protected IWebObjectFactory GetAdapterFactory(Type originalControlType)
        {
            Debug.Assert(_parentConfigName == null);

            Type controlType          = originalControlType;
            IWebObjectFactory factory = LookupControl(controlType, true); // Look in type cache

            // Walk up hierarchy looking for registered adapters.
            // Stop when we get to the base control.

            while (factory == null && controlType != _baseControlType)
            {
                factory = LookupControl(controlType);
                if (factory == null)
                {
                    controlType = controlType.BaseType;
                }
            }

            // Could not find one in the current hierarchy. So, look it up in
            // the parent config if there is one.

            if (factory == null && _parentConfig != null)
            {
                factory = _parentConfig.GetAdapterFactory(originalControlType);
            }

            if (factory == null)
            {
                throw new Exception(
                          SR.GetString(SR.IndividualDeviceConfig_ControlWithIncorrectPageAdapter,
                                       controlType.FullName, _pageAdapterType.FullName));
            }

            if (controlType != originalControlType)
            {
                // Add to lookup cache, so the next lookup won't require
                // traversing the hierarchy.

                // Grab writer lock...
                using (new ReaderWriterLockResource(_controlAdapterTypesLock,
                                                    true))
                {
                    _controlAdapterLookupCache[originalControlType] = factory;
                }
            }

            return(factory);
        }