/// <summary> /// 加载自定义程序集 /// </summary> private static void LoadCustomAssembly(HashSet <string> loadLocations) { //dll加载的目录 var dllScanAndLoadPath = ScriptEngineCSharpConfigHelper.GetDllScanAndLoadPath(); _logger.LogInformation($"bamboo script engine csharp compnent -> scan config dirs: [{string.Join(",", dllScanAndLoadPath)}]"); foreach (var dllPath in dllScanAndLoadPath) { //如果配置的是文件,则按文件加载 if (File.Exists(dllPath)) { loadLocations.Add(dllPath); } //如果配置的是文件夹,那么将目录下的所有dll都加载 else if (Directory.Exists(dllPath)) { //拿到目录下全部dll var dlls = Directory.GetFiles(dllPath, "*.dll", SearchOption.AllDirectories) ?? new string[0]; foreach (var item in dlls) { loadLocations.Add(item); } } } }
/// <summary> /// Create Assembly whick will run /// </summary> /// <param name="script"></param> /// <param name="errorMsg"></param> /// <returns></returns> private Assembly CreateAsmExecutor(string script, out string errorMsg) { errorMsg = null; var assemblyName = _scriptHash; var references = ReferenceManager.GetMetaDataReferences()[_currentAppName]; var compilation = CSharpCompilation.Create(assemblyName, new[] { GetSyntaxTree(script) }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithOptimizationLevel(ScriptEngineCSharpConfigHelper.IsDebugModeCompile() ? OptimizationLevel.Debug : OptimizationLevel.Release)); Assembly assembly = null; using (var assemblyStream = new MemoryStream()) { using (var pdbStream = new MemoryStream()) { var emitExecutionResult = compilation.Emit(assemblyStream, pdbStream); if (emitExecutionResult.Success) { var assemblyBytes = assemblyStream.GetBuffer(); var pdbBytes = pdbStream.GetBuffer(); assembly = Assembly.Load(assemblyBytes, pdbBytes); //output files if (ScriptEngineCSharpConfigHelper.IsIsOutPutCompileFiles()) { OutputDynamicScriptAllFile(script, assemblyName, assemblyBytes, pdbBytes); } } else { var msgs = new StringBuilder(); foreach (var msg in emitExecutionResult.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => string.Format("[{0}]:{1}({2})", d.Id, d.GetMessage(), d.Location.GetLineSpan().StartLinePosition))) { msgs.AppendLine(msg); } if (ScriptEngineCSharpConfigHelper.IsIsOutPutCompileFiles()) { WriteDynamicScriptCs(Path.Combine(EnsureOutputPath(), assemblyName + ".cs"), script); } errorMsg = msgs.ToString(); _logger.LogError(string.Format("{0}:{1}:{2}:{3}", "CSharp", _currentAppName, errorMsg, _scriptHash)); } } } _logger.LogInformation($"CreateAsmExecutor -> _context: CSharp, {_currentAppName},{_scriptHash} _scriptTypeDict:{_scriptTypeDict?.Count} _metadataReferences:{ ReferenceManager.GetMetaDataReferences()[_currentAppName]?.Count}"); return(assembly); }
/// <summary> /// 加载安装包程序集 /// </summary> /// <param name="loadLocations"></param> private static void LoadPackageAssembly(HashSet <string> loadLocations) { //download var logger = NullLogger.Instance; CancellationToken cancellationToken = CancellationToken.None; //dll下载目录 var downloadPath = Directory.CreateDirectory(Path.Combine(AppContext.BaseDirectory, Consts.BambooScriptEnginePackageDownload)).FullName; ConcurrentBag <string> concurrentBag = new ConcurrentBag <string>(); //并行下载 ScriptEngineCSharpConfigHelper.GetInstallPackageSourceDic().AsParallel().ForAll(current => //foreach (var current in ScriptEngineCSharpConfigHelper.GetInstallPackageSourceDic())//Debug { SourceCacheContext cache = new SourceCacheContext(); var package = current.Key; var currentVersionPath = Path.Combine(downloadPath, package.PackageId.ToLower(), package.Version.ToLower()); //先查询本地文件是否存在,如果存在,就无需再去下载 if (Directory.Exists(currentVersionPath)) { var file = Directory.GetFiles(currentVersionPath, "*.dll", SearchOption.AllDirectories).FirstOrDefault(t => Path.GetFileName(t).Equals(string.Concat(package.PackageId, ".dll"))); if (file != null) { concurrentBag.Add(file); return; } } //标记是否当前包已经成功匹配,如果成功,则不会继续在后续的源中查找 bool isCurrentPackageMatchSuccess = false; foreach (var source in current.Value) { if (isCurrentPackageMatchSuccess) { break; } SourceRepository repository = Repository.Factory.GetCoreV3(source); FindPackageByIdResource resource = repository.GetResourceAsync <FindPackageByIdResource>().Result; //当前源没有找到这个包,换下一个源下载 if (!resource.DoesPackageExistAsync(package.PackageId, new NuGetVersion(package.Version), cache, logger, cancellationToken).Result) { continue; } using (MemoryStream packageStream = new MemoryStream()) { //复制包 if (!resource.CopyNupkgToStreamAsync(package.PackageId, new NuGetVersion(package.Version), packageStream, cache, logger, cancellationToken).Result) { _logger.LogError($"copy package of {package.PackageId} {package.Version} from source [{source}] error"); break; } using (PackageArchiveReader packageReader = new PackageArchiveReader(packageStream)) { _logger.LogDebug($"copy package of {package.PackageId} {package.Version} from source [{source}] success"); var files = packageReader.GetFiles().Where(t => Path.GetExtension(t).Equals(".dll")).ToArray(); foreach (var file in files) { if (isCurrentPackageMatchSuccess) { break; } //按顺序匹配对应版本的dll foreach (var matchItem in Consts.MatchDllVersionFromNugetPackageSequnce) { if (file.Contains(matchItem)) { var fileFullPath = Path.Combine(currentVersionPath, file); if (!File.Exists(fileFullPath)) { packageReader.ExtractFile(file, fileFullPath, logger); } concurrentBag.Add(fileFullPath); isCurrentPackageMatchSuccess = true; break; } } } } } } //}//DEBUG }); //添加到dll引用目录 loadLocations.AddRange(concurrentBag); }