internal static IObjectHandle GetCustomLoader(ICustomLoaderHelperFunctions helperFunctions, string appConfigMetabasePath, string configFilePath, string customLoaderPhysicalPath, out AppDomain newlyCreatedAppDomain) {
            // Step 1: Does the host allow custom loaders?

            bool? customLoaderIsEnabled = helperFunctions.CustomLoaderIsEnabled;
            if (customLoaderIsEnabled.HasValue) {
                if ((bool)customLoaderIsEnabled) {
                    // The custom loader is enabled; move on to the next step.
                }
                else {
                    // The custom loader is disabled, fail.
                    throw new NotSupportedException(ApplicationServicesStrings.CustomLoader_ForbiddenByHost);
                }
            }
            else {
                // The host hasn't set a policy, so we'll fall back to our default logic of checking the application's trust level.
                if (!IsFullyTrusted(helperFunctions, appConfigMetabasePath)) {
                    throw new NotSupportedException(ApplicationServicesStrings.CustomLoader_NotInFullTrust);
                }
            }

            // Step 2: Create the new AD

            string binFolderPhysicalPath = helperFunctions.MapPath("/bin/");

            AppDomainSetup setup = new AppDomainSetup() {
                PrivateBinPathProbe = "*",  // disable loading from app base
                PrivateBinPath = binFolderPhysicalPath,
                ApplicationBase = helperFunctions.AppPhysicalPath,
                TargetFrameworkName = _customLoaderTargetFrameworkName
            };

            if (configFilePath != null) {
                setup.ConfigurationFile = configFilePath;
            }

            AppDomain newAppDomainForCustomLoader = AppDomain.CreateDomain("aspnet-custom-loader-" + Guid.NewGuid(), null, setup);
            try {
                // Step 3: Instantiate helper in new AD so that we can get a reference to the loader
                CustomLoaderHelper helper = (CustomLoaderHelper)newAppDomainForCustomLoader.CreateInstanceAndUnwrap(_customLoaderAssemblyName, _customLoaderTypeName,
                    ignoreCase: false,
                    bindingAttr: BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance,
                    binder: null,
                    args: null,
                    culture: null,
                    activationAttributes: null);
                ObjectHandle ohCustomLoader = helper.GetCustomLoaderImpl(customLoaderPhysicalPath);

                // If we got this far, success!
                newlyCreatedAppDomain = newAppDomainForCustomLoader;
                return ohCustomLoader;
            }
            catch {
                // If something went wrong, kill the new AD.
                AppDomain.Unload(newAppDomainForCustomLoader);
                throw;
            }
        }
        private static bool IsFullyTrusted(ICustomLoaderHelperFunctions helperFunctions, string appConfigMetabasePath)
        {
            // The managed configuration system hasn't yet been instantiated but the IIS native config system understands
            // ASP.NET configuration and honors hierarchy and section locking.

            try {
                // Must exactly match <trust level="Full" />, as this is what ApplicationManager expects.
                string trustLevel = helperFunctions.GetTrustLevel(appConfigMetabasePath);
                return(String.Equals("Full", trustLevel, StringComparison.Ordinal));
            }
            catch {
                // If any of the sections are locked or there is a config error, bail.
                return(false);
            }
        }
        private static bool IsFullyTrusted(ICustomLoaderHelperFunctions helperFunctions, string appConfigMetabasePath) {
            // The managed configuration system hasn't yet been instantiated but the IIS native config system understands
            // ASP.NET configuration and honors hierarchy and section locking.

            try {
                // Must exactly match <trust level="Full" />, as this is what ApplicationManager expects.
                string trustLevel = helperFunctions.GetTrustLevel(appConfigMetabasePath);
                return String.Equals("Full", trustLevel, StringComparison.Ordinal);
            }
            catch {
                // If any of the sections are locked or there is a config error, bail.
                return false;
            }
        }
        internal static IObjectHandle GetCustomLoader(ICustomLoaderHelperFunctions helperFunctions, string appConfigMetabasePath, string configFilePath, string customLoaderPhysicalPath, out AppDomain newlyCreatedAppDomain)
        {
            // Step 1: Does the host allow custom loaders?

            bool?customLoaderIsEnabled = helperFunctions.CustomLoaderIsEnabled;

            if (customLoaderIsEnabled.HasValue)
            {
                if ((bool)customLoaderIsEnabled)
                {
                    // The custom loader is enabled; move on to the next step.
                }
                else
                {
                    // The custom loader is disabled, fail.
                    throw new NotSupportedException(ApplicationServicesStrings.CustomLoader_ForbiddenByHost);
                }
            }
            else
            {
                // The host hasn't set a policy, so we'll fall back to our default logic of checking the application's trust level.
                if (!IsFullyTrusted(helperFunctions, appConfigMetabasePath))
                {
                    throw new NotSupportedException(ApplicationServicesStrings.CustomLoader_NotInFullTrust);
                }
            }

            // Step 2: Create the new AD

            string binFolderPhysicalPath = helperFunctions.MapPath("/bin/");

            AppDomainSetup setup = new AppDomainSetup()
            {
                PrivateBinPathProbe = "*",  // disable loading from app base
                PrivateBinPath      = binFolderPhysicalPath,
                ApplicationBase     = helperFunctions.AppPhysicalPath,
                TargetFrameworkName = _customLoaderTargetFrameworkName
            };

            if (configFilePath != null)
            {
                setup.ConfigurationFile = configFilePath;
            }

            AppDomain newAppDomainForCustomLoader = AppDomain.CreateDomain("aspnet-custom-loader-" + Guid.NewGuid(), null, setup);

            try {
                // Step 3: Instantiate helper in new AD so that we can get a reference to the loader
                CustomLoaderHelper helper = (CustomLoaderHelper)newAppDomainForCustomLoader.CreateInstanceAndUnwrap(_customLoaderAssemblyName, _customLoaderTypeName,
                                                                                                                    ignoreCase: false,
                                                                                                                    bindingAttr: BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance,
                                                                                                                    binder: null,
                                                                                                                    args: null,
                                                                                                                    culture: null,
                                                                                                                    activationAttributes: null);
                ObjectHandle ohCustomLoader = helper.GetCustomLoaderImpl(customLoaderPhysicalPath);

                // If we got this far, success!
                newlyCreatedAppDomain = newAppDomainForCustomLoader;
                return(ohCustomLoader);
            }
            catch {
                // If something went wrong, kill the new AD.
                AppDomain.Unload(newAppDomainForCustomLoader);
                throw;
            }
        }