/// <summary>
        /// Load an IL or NI assembly from its file path.
        /// </summary>
        internal Assembly LoadFrom(string assemblyPath)
        {
            ValidateAssemblyPath(assemblyPath, "assemblyPath");

            Assembly     asmLoaded;
            AssemblyName assemblyName = GetAssemblyName(assemblyPath);

            // Probe the assembly cache
            if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
            {
                return(asmLoaded);
            }

            // Prepare to load the assembly
            lock (s_syncObj)
            {
                // Probe the cache again in case it's already loaded
                if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
                {
                    return(asmLoaded);
                }

                // Load the assembly through 'LoadFromNativeImagePath' or 'LoadFromAssemblyPath'
                asmLoaded = assemblyPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase)
                    ? _activeLoadContext.LoadFromNativeImagePath(assemblyPath, null)
                    : _activeLoadContext.LoadFromAssemblyPath(assemblyPath);

                if (asmLoaded != null)
                {
                    // Add the loaded assembly to the cache
                    s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded);
                    // Add its parent path to our probing paths
                    string parentPath = Path.GetDirectoryName(assemblyPath);
                    if (!_probingPaths.Contains(parentPath))
                    {
                        _probingPaths.Add(parentPath);
                    }
                }
            }

            // Raise AssemblyLoad event
            OnAssemblyLoaded(asmLoaded);
            return(asmLoaded);
        }
        /// <summary>
        /// The handler for the Resolving event
        /// </summary>
        private Assembly Resolve(AssemblyLoadContext loadContext, AssemblyName assemblyName)
        {
            // Probe the assembly cache
            Assembly asmLoaded;

            if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
            {
                return(asmLoaded);
            }

            // Prepare to load the assembly
            lock (s_syncObj)
            {
                // Probe the cache again in case it's already loaded
                if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
                {
                    return(asmLoaded);
                }

                // Search the specified assembly in probing paths, and load it through 'LoadFromAssemblyPath' if the file exists and matches the requested AssemblyName.
                // If the CultureName of the requested assembly is not NullOrEmpty, then it's a resources.dll and we need to search corresponding culture sub-folder.
                bool   isAssemblyFileFound = false, isAssemblyFileMatching = false;
                string asmCultureName = assemblyName.CultureName ?? string.Empty;
                string asmFilePath    = null;

                for (int i = 0; i < _probingPaths.Length; i++)
                {
                    string probingPath    = _probingPaths[i];
                    string asmCulturePath = Path.Combine(probingPath, asmCultureName);
                    for (int k = 0; k < _extensions.Length; k++)
                    {
                        string asmFileName = assemblyName.Name + _extensions[k];
                        asmFilePath = Path.Combine(asmCulturePath, asmFileName);

                        if (File.Exists(asmFilePath))
                        {
                            isAssemblyFileFound = true;
                            AssemblyName asmNameFound = AssemblyLoadContext.GetAssemblyName(asmFilePath);
                            if (IsAssemblyMatching(assemblyName, asmNameFound))
                            {
                                isAssemblyFileMatching = true;
                                break;
                            }
                        }
                    }

                    if (isAssemblyFileFound && isAssemblyFileMatching)
                    {
                        break;
                    }
                }

                // We failed to find the assembly file; or we found the file, but the assembly file doesn't match the request.
                // In this case, return null so that other Resolving event handlers can kick in to resolve the request.
                if (!isAssemblyFileFound || !isAssemblyFileMatching)
                {
#if !UNIX
                    //Try loading from GAC
                    if (!TryFindInGAC(assemblyName, out asmFilePath))
                    {
                        return(null);
                    }
#else
                    return(null);
#endif
                }

                asmLoaded = asmFilePath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase)
                                ? loadContext.LoadFromNativeImagePath(asmFilePath, null)
                                : loadContext.LoadFromAssemblyPath(asmFilePath);
                if (asmLoaded != null)
                {
                    // Add the loaded assembly to the cache
                    s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded);
                }
            }

            return(asmLoaded);
        }