/// <summary> /// Function to catch and handle an exception. /// </summary> /// <typeparam name="T">The type of exception. This value must be or inherit from the <see cref="Exception"/> type.</typeparam> /// <param name="ex">Exception to pass to the handler.</param> /// <param name="handler">A method that is called to handle the exception.</param> /// <param name="log">[Optional] A logger that will capture the exception, or <b>null</b> to disable logging of this exception.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="ex"/> parameter is <b>null</b>.</exception> /// <remarks> /// This is a convenience method used to catch an exception and then handle it with the supplied <paramref name="handler"/> method. The handler method must take a parameter /// that has a type that is or derives from <see cref="Exception"/>. /// </remarks> public static void Catch <T>(this T ex, Action <T> handler, IGorgonLog log = null) where T : Exception { if ((ex == null) || (handler == null)) { return; } log?.LogException(ex); handler(ex); }
/// <summary>Function to load all the specified plug in assemblies.</summary> /// <param name="pluginCache">The plugin cache that will hold the plug in assembies.</param> /// <param name="pluginAssemblyFiles">The list of plug in assembly paths to load.</param> /// <param name="log">The application logging interface.</param> /// <returns>A list of <see cref="PlugInAssemblyState"/> objects for each plug in assembly loaded.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="pluginAssemblyFiles" /> parameter is <b>null</b></exception> public static IReadOnlyList <PlugInAssemblyState> ValidateAndLoadAssemblies(this GorgonMefPlugInCache pluginCache, IEnumerable <FileInfo> pluginAssemblyFiles, IGorgonLog log) { if (pluginAssemblyFiles == null) { throw new ArgumentNullException(nameof(pluginAssemblyFiles)); } var records = new List <PlugInAssemblyState>(); // We use this to determine whether the plug in can be loaded into the current platform. AssemblyPlatformType currentPlatform = IntPtr.Size == 8 ? AssemblyPlatformType.x64 : AssemblyPlatformType.x86; foreach (FileInfo file in pluginAssemblyFiles) { // If we've already got the assembly loaded into this cache, then there's no need to try and load it. if (pluginCache.PlugInAssemblies?.Any(item => string.Equals(item, file.FullName, StringComparison.OrdinalIgnoreCase)) ?? false) { continue; } if (!file.Exists) { log.Print($"[ERROR] Plug in '{file.FullName}' was not found.", LoggingLevel.Verbose); records.Add(new PlugInAssemblyState(file.FullName, Resources.GOREDIT_PLUGIN_LOAD_FAIL_NOT_FOUND, false)); continue; } (bool isManaged, AssemblyPlatformType platformType) = GorgonMefPlugInCache.IsManagedAssembly(file.FullName); if ((!isManaged) || (platformType == AssemblyPlatformType.Unknown)) { log.Print($"[WARNING] Skipping '{file.FullName}'. Not a valid .NET assembly.", LoggingLevel.Verbose); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_NOT_DOT_NET, file.Name), false)); continue; } // Ensure that our platform type matches (AnyCPU is exempt and will always run, and DLLs don't allow Prefer 32 bit). if ((currentPlatform == AssemblyPlatformType.x86) && (platformType == AssemblyPlatformType.x64)) { log.Print($"[ERROR] Cannot load assembly '{file.FullName}', currently executing in an x86 environment, but the assembly is x64.", LoggingLevel.Simple); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_PLATFORM_MISMATCH, file.Name, platformType, currentPlatform), true)); continue; } if ((currentPlatform == AssemblyPlatformType.x64) && (platformType == AssemblyPlatformType.x86)) { log.Print($"[ERROR] Cannot load assembly '{file.FullName}', currently executing in an x64 environment, but the assembly is x86.", LoggingLevel.Simple); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_PLATFORM_MISMATCH, file.Name, platformType, currentPlatform), true)); continue; } try { log.Print($"Loading plug in assembly '{file.FullName}'...", LoggingLevel.Simple); pluginCache.LoadPlugInAssemblies(file.DirectoryName, file.Name); records.Add(new PlugInAssemblyState(file.FullName, string.Empty, true)); } catch (Exception ex) { log.Print($"ERROR: Cannot load plug in assembly '{file.FullName}'.", LoggingLevel.Simple); log.LogException(ex); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_EXCEPTION, file.Name, ex.Message), true)); } } return(records); }