public CommonReturnValue GetInlinePluginModuleSource(string inlineEntryId, out InlineModuleManifestEntry existingInlineEntry, out string source) { source = null; existingInlineEntry = null; var pluginAssembly = this.PluginAssemblies.FirstOrDefault(p => p.InlineEntryId != null && p.InlineEntryId.Equals(inlineEntryId, StringComparison.Ordinal) && p.IsInline); if (pluginAssembly == null) { return(CommonReturnValue.UserError($"An inline module with the Id '{inlineEntryId}' does not exist")); } try { existingInlineEntry = InlineModuleManifest.Instance.GetEntryById(pluginAssembly.InlineEntryId); var sourcePath = System.IO.Path.Combine(InlinePluginSourcePath, existingInlineEntry.Id); if (System.IO.File.Exists(sourcePath)) { source = System.IO.File.ReadAllText(sourcePath); return(CommonReturnValue.Success()); } else { return(CommonReturnValue.UserError($"Failed to find source at: {sourcePath}")); } } catch (Exception e) { SessionLog.Warning("Failed to fetch file of plugin module with InstanceId = {0}; {1}", pluginAssembly.InstanceId, pluginAssembly.Assembly.FullName); SessionLog.Exception(e); } return(CommonReturnValue.Success()); }
public bool LoadOrUpdateInlineAssembly(InlineModuleManifestEntry inlineEntry, string code, out List <string> errorList) { errorList = null; var existingPluginAssembly = this.PluginAssemblies.FirstOrDefault(p => p.InlineEntryId != null && p.InlineEntryId.Equals(inlineEntry.Id, StringComparison.Ordinal) && p.IsInline); if (existingPluginAssembly != null) { var existingAsmCtx = AssemblyLoadContext.GetLoadContext(existingPluginAssembly.Assembly); // unload existing PluginAssembly existingPluginAssembly.Unload(); this._pluginAssemblies.Remove(existingPluginAssembly); Instance.CompileCodeIntoAssemblyContext(inlineEntry, code); // if (!ParsePluginAssembly(newAssembly, out var pluginInfoList, out errorList, checkForConflict: false)) // { // return false; // } //existingPluginAssembly.UpdatePluginList(pluginInfoList); //SessionLog.Info($"Assembly {existingPluginAssembly.Assembly.FullName} updated"); } else { // new? Instance.CompileCodeIntoAssemblyContext(inlineEntry, code); } // TODO: Perhaps this can be optimised to run only on apps that are affected by plugin change ServerMethodManager.RebuildCacheForAllApps(); return(true); }
private void CompileCodeIntoAssemblyContext(InlineModuleManifestEntry inlineEntry, string code) { var ctxName = $"Inline Plugin Context {++_asmCtxCounter}"; var pluginPath = Path.GetFullPath("plugins"); var asmCtx = new PluginAssemblyLoadContext(pluginPath, ctxName, true /*enable unloading*/); ASM_CTXES.Add(asmCtx); SessionLog.Info($"Created {ctxName} for {inlineEntry.Name}".PadRight(35)); var assemblyBytes = CSharpCompilerHelper.CompileIntoAssembly(inlineEntry.Name, code, out var problems); if ((problems != null && problems.Count == 0)) { Assembly assembly = null; try { using (var ms = new MemoryStream(assemblyBytes)) { assembly = asmCtx.LoadFromStream(ms); ParseAndLoadPluginAssembly(asmCtx, assembly, inlineEntry.Id); } } catch (Exception ee) { SessionLog.Error($"Failed to load inline plugin assembly '{assembly?.FullName}' {inlineEntry.Name}/{inlineEntry.Id}. See exception that follows."); SessionLog.Exception(ee); } } else { SessionLog.Error($"Inline plugin {inlineEntry.Name} ({inlineEntry.Id}) failed to compile with the following error(s): {string.Join(", ", problems)}"); } }