/// <summary> /// Compile and register dyncode app api controller (for new or updated app api). /// </summary> /// <param name="values"></param> /// <returns></returns> public async ValueTask <bool> PrepareController(RouteValueDictionary values) { var wrapLog = Log.Call <bool>(); var apiFile = (string)values["apiFile"]; var dllName = (string)values["dllName"]; // If we have a key (that controller is compiled and registered, but not updated) controller was prepared before, so just return values. // Alternatively remove older version of AppApi controller (if we got updated flag from file system watcher). if (_compiledAppApiControllers.TryGetValue(apiFile, out var updated)) { Log.Add($"_compiledAppApiControllers have value: {updated} for: {apiFile}."); if (updated) { RemoveController(dllName, apiFile); } else { return(wrapLog( $"ok, nothing to do, AppApi Controller is already compiled and added to ApplicationPart: {apiFile}.", true)); } } Log.Add($"We need to prepare controller for: {apiFile}."); // Check for AppApi file if (!File.Exists(apiFile)) { return(wrapLog($"Error, missing AppApi file {apiFile}.", false)); } // note: this may look like something you could optimize/cache the result, but that's a bad idea // because when the file changes, the type-object will be different, so please don't optimize :) // Check for AppApi source code var apiCode = await File.ReadAllTextAsync(apiFile); if (string.IsNullOrWhiteSpace(apiCode)) { return(wrapLog($"Error, missing AppApi code in file {apiFile}.", false)); } // Build new AppApi Controller Log.Add($"Compile assembly: {apiFile}, {dllName}"); var assembly = new Compiler().Compile(apiFile, dllName); // Add new key to concurrent dictionary, before registering new AppAPi controller. if (!_compiledAppApiControllers.TryAdd(apiFile, false)) { return(wrapLog($"Error, while adding key {apiFile} to concurrent dictionary, so will not register AppApi Controller to avoid duplicate controller routes.", false)); } // Register new AppApi Controller. AddController(dllName, assembly); return(wrapLog($"ok, Controller is compiled and added to ApplicationParts: {apiFile}.", true)); }