public PluginContainer GetPlugin(string path, ILogger logger) { var loadContext = new PluginLoadContext(Path.GetFileNameWithoutExtension(path) + "LoadContext", path); var assembly = loadContext.LoadFromAssemblyPath(path); return(HandlePlugin(loadContext, assembly, path, logger)); }
internal PluginContainer HandlePlugin(PluginLoadContext loadContext, Assembly assembly, string path, ILogger logger) { Type pluginType = assembly.GetTypes().FirstOrDefault(type => type.IsSubclassOf(typeof(PluginBase))); PluginBase plugin; if (pluginType == null || pluginType.GetConstructor(Array.Empty <Type>()) == null) { plugin = default; logger?.LogError("Loaded assembly contains no type implementing PluginBase with public parameterless constructor."); return(new PluginContainer(new PluginInfo(Path.GetFileNameWithoutExtension(path)), path)); } else { logger?.LogInformation("Creating plugin instance..."); plugin = (PluginBase)Activator.CreateInstance(pluginType); } string name = assembly.GetName().Name; var attribute = pluginType.GetCustomAttribute <PluginAttribute>(); var info = attribute != null ? new PluginInfo(name, attribute) : new PluginInfo(name); if (attribute == null) { logger?.LogWarning($"Plugin is missing {nameof(PluginAttribute)}. Name defaults to '{info.Name}', version defaults to {info.Version}."); } return(new PluginContainer(plugin, info, assembly, loadContext, path)); }
public PluginContainer GetPlugin(string path, ILogger logger) { string name = Path.GetFileNameWithoutExtension(path); FileStream fileStream; try { fileStream = File.OpenRead(path); } catch { logger.LogError($"Reloading '{Path.GetFileName(path)}' failed, file is not accessible."); return(new PluginContainer(new PluginInfo(name), name)); } SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(SourceText.From(fileStream)); fileStream.Dispose(); var compilation = CSharpCompilation.Create(name, new[] { syntaxTree }, MetadataReferences, CompilationOptions); using var memoryStream = new MemoryStream(); EmitResult emitResult = compilation.Emit(memoryStream); if (!emitResult.Success) { if (logger != null) { foreach (var diagnostic in emitResult.Diagnostics) { if (diagnostic.Severity != DiagnosticSeverity.Error || diagnostic.IsWarningAsError) { continue; } logger.LogError($"Compilation failed: {diagnostic.Location} {diagnostic.GetMessage()}"); } } return(new PluginContainer(new PluginInfo(name), name)); } else { memoryStream.Seek(0, SeekOrigin.Begin); var loadContext = new PluginLoadContext(name + "LoadContext", path); var assembly = loadContext.LoadFromStream(memoryStream); return(PluginProviderSelector.CompiledPluginProvider.HandlePlugin(loadContext, assembly, path, logger)); } }