/// <summary> /// Initializes a new instance of the <see cref="DmbProvider"/> class. /// </summary> /// <param name="compileJob">The value of <see cref="CompileJob"/>.</param> /// <param name="ioManager">The value of <see cref="ioManager"/>.</param> /// <param name="onDispose">The value of <see cref="onDispose"/>.</param> /// <param name="directoryAppend">The optional value of <see cref="directoryAppend"/>.</param> public DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose, string directoryAppend = null) { CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob)); this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose)); this.directoryAppend = directoryAppend ?? String.Empty; }
/// <inheritdoc /> public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken) { if (job == null) { throw new ArgumentNullException(nameof(job)); } var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false); if (newProvider == null) { return; } // Do this first, because it's entirely possible when we set the tcs it will immediately need to be applied if (started) { await gitHubDeploymentManager.StageDeployment( newProvider.CompileJob, cancellationToken) .ConfigureAwait(false); } lock (jobLockCounts) { nextDmbProvider?.Dispose(); nextDmbProvider = newProvider; // Oh god dammit var temp = newerDmbTcs; newerDmbTcs = new TaskCompletionSource <object>(); temp.SetResult(nextDmbProvider); } }
/// <inheritdoc /> protected override string FormatTestMerge( RepositorySettings repositorySettings, CompileJob compileJob, TestMerge testMerge, string remoteRepositoryOwner, string remoteRepositoryName, bool updated) => String.Format( CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}{8}", Environment.NewLine, repositorySettings.ShowTestMergeCommitters.Value ? String.Format( CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty, testMerge.TargetCommitSha, testMerge.Comment != null ? String.Format( CultureInfo.InvariantCulture, "{0}{0}##### Comment{0}{1}", Environment.NewLine, testMerge.Comment) : String.Empty, updated ? "Updated" : "Deployed", Metadata.Name, compileJob.RevisionInformation.OriginCommitSha, compileJob.RevisionInformation.CommitSha, compileJob.GitHubDeploymentId.HasValue ? $"{Environment.NewLine}[GitHub Deployments](https://github.com/{remoteRepositoryOwner}/{remoteRepositoryName}/deployments/activity_log?environment=TGS%3A%20{Metadata.Name})" : String.Empty);
public void Dispose() => cleanupCts.Dispose(); // we don't dispose nextDmbProvider here, since it might be the only thing we have /// <summary> /// Delete the <see cref="Api.Models.Internal.CompileJob.DirectoryName"/> of <paramref name="job"/> /// </summary> /// <param name="job">The <see cref="CompileJob"/> to clean</param> void CleanJob(CompileJob job) { async Task HandleCleanup() { var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token); var remoteDeploymentManager = remoteDeploymentManagerFactory.CreateRemoteDeploymentManager( metadata, job); // DCT: None available var deploymentJob = remoteDeploymentManager.MarkInactive(job, default); var otherTask = cleanupTask; await Task.WhenAll(otherTask, deleteJob, deploymentJob).ConfigureAwait(false); } lock (jobLockCounts) if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1) { jobLockCounts.Remove(job.Id); logger.LogDebug("Cleaning lock-free compile job {0} => {1}", job.Id, job.DirectoryName); cleanupTask = HandleCleanup(); } else { var decremented = --jobLockCounts[job.Id]; logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented); } }
/// <inheritdoc /> public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken) { if (job == null) { throw new ArgumentNullException(nameof(job)); } CompileJob finalCompileJob = null; //now load the entire compile job tree await databaseContextFactory.UseContext(async db => finalCompileJob = await db.CompileJobs.Where(x => x.Id == job.Id) .Include(x => x.Job).ThenInclude(x => x.StartedBy) .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy) .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy) .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); //can't wait to see that query if (finalCompileJob == null) { //lol git f****d return; } var newProvider = await FromCompileJob(finalCompileJob, cancellationToken).ConfigureAwait(false); if (newProvider == null) { return; } lock (this) { nextDmbProvider?.Dispose(); nextDmbProvider = newProvider; newerDmbTcs.SetResult(nextDmbProvider); newerDmbTcs = new TaskCompletionSource <object>(); } }
/// <inheritdoc /> public Task PostDeploymentComments( CompileJob compileJob, RevisionInformation previousRevisionInformation, RepositorySettings repositorySettings, string repoOwner, string repoName, CancellationToken cancellationToken) => Task.CompletedTask;
/// <summary> /// Formats a comment for a given <paramref name="testMerge"/>. /// </summary> /// <param name="repositorySettings">The <see cref="RepositorySettings"/> to use.</param> /// <param name="compileJob">The test merge's <see cref="CompileJob"/>.</param> /// <param name="testMerge">The <see cref="TestMerge"/>.</param> /// <param name="remoteRepositoryOwner">The <see cref="Api.Models.Internal.IGitRemoteInformation.RemoteRepositoryOwner"/>.</param> /// <param name="remoteRepositoryName">The <see cref="Api.Models.Internal.IGitRemoteInformation.RemoteRepositoryName"/>.</param> /// <param name="updated">If <see langword="false"/> <paramref name="testMerge"/> is new, otherwise it has been updated to a different <see cref="Api.Models.TestMergeParameters.TargetCommitSha"/>.</param> /// <returns>A <see cref="Task"/> representing the running operation.</returns> protected abstract string FormatTestMerge( RepositorySettings repositorySettings, CompileJob compileJob, TestMerge testMerge, string remoteRepositoryOwner, string remoteRepositoryName, bool updated);
public void Dispose() => cleanupCts.Dispose(); // we don't dispose nextDmbProvider here, since it might be the only thing we have /// <summary> /// Delete the <see cref="Api.Models.Internal.CompileJob.DirectoryName"/> of <paramref name="job"/> /// </summary> /// <param name="job">The <see cref="CompileJob"/> to clean</param> void CleanJob(CompileJob job) { async Task HandleCleanup() { var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token); Task otherTask; // lock (this) //already locked below otherTask = cleanupTask; await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false); } lock (this) if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1) { jobLockCounts.Remove(job.Id); logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName); cleanupTask = HandleCleanup(); } else { var decremented = --jobLockCounts[job.Id]; logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented); } }
/// <inheritdoc /> protected override string FormatTestMerge( RepositorySettings repositorySettings, CompileJob compileJob, TestMerge testMerge, string remoteRepositoryOwner, string remoteRepositoryName, bool updated) => String.Format( CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Merge Request: {2}{0}Server: {7}{3}", Environment.NewLine, repositorySettings.ShowTestMergeCommitters.Value ? String.Format( CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty, testMerge.TargetCommitSha, testMerge.Comment != null ? String.Format( CultureInfo.InvariantCulture, "{0}{0}##### Comment{0}{1}", Environment.NewLine, testMerge.Comment) : String.Empty, updated ? "Updated" : "Deployed", Metadata.Name, compileJob.RevisionInformation.OriginCommitSha, compileJob.RevisionInformation.CommitSha);
/// <inheritdoc /> public async Task StartAsync(CancellationToken cancellationToken) { CompileJob cj = null; await databaseContextFactory.UseContext(async (db) => { cj = await db .CompileJobs .AsQueryable() .Where(x => x.Job.Instance.Id == metadata.Id) .OrderByDescending(x => x.Job.StoppedAt) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); }) .ConfigureAwait(false); if (cj == default(CompileJob)) { return; } await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false); started = true; // we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet }
/// <inheritdoc /> public Task StageDeployment( CompileJob compileJob, CancellationToken cancellationToken) => UpdateDeployment( compileJob, "The deployment succeeded and will be applied a the next server reboot.", DeploymentState.Pending, cancellationToken);
private static void CleanupCompile() { UdonSharpUtils.ClearAsyncProgressBar(); EditorApplication.UnlockReloadAssemblies(); CurrentJob = null; }
public static int QueueCompileJob(string code, string[] assemblyPaths, bool sync = false) { CompileJob job = new CompileJob(NextJobId); compileJobs.Add(job); job.Start(code, assemblyPaths, sync); return(job.jobId); }
#pragma warning restore CA1506 /// <inheritdoc /> #pragma warning disable CA1506 // TODO: Decomplexify public async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken) { List <long> jobIdsToSkip; // don't clean locked directories lock (this) jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList(); List <string> jobUidsToNotErase = null; // find the uids of locked directories await databaseContextFactory.UseContext(async db => { jobUidsToNotErase = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)).Select(x => x.DirectoryName.Value.ToString().ToUpperInvariant()).ToListAsync(cancellationToken).ConfigureAwait(false); }).ConfigureAwait(false); // add the other exemption if (exceptThisOne != null) { jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant()); } // cleanup await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false); var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false); int deleting = 0; var tasks = directories.Select(async x => { var nameOnly = ioManager.GetFileName(x); if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant())) { return; } try { ++deleting; await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { throw; } catch (Exception e) { logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e); } }).ToList(); if (deleting > 0) { logger.LogDebug("Cleaning {0} unused game folders...", deleting); await Task.WhenAll().ConfigureAwait(false); } }
async Task UpdateDeployment( CompileJob compileJob, string description, DeploymentState deploymentState, CancellationToken cancellationToken) { if (compileJob == null) { throw new ArgumentNullException(nameof(compileJob)); } if (!compileJob.GitHubRepoId.HasValue || !compileJob.GitHubDeploymentId.HasValue) { logger.LogTrace("Not updating deployment as it is missing a repo ID or deployment ID."); return; } logger.LogTrace("Updating deployment {0} to {1}...", compileJob.GitHubDeploymentId.Value, deploymentState); string gitHubAccessToken = null; await databaseContextFactory.UseContext( async databaseContext => gitHubAccessToken = await databaseContext .RepositorySettings .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .Select(x => x.AccessToken) .FirstAsync(cancellationToken) .ConfigureAwait(false)) .ConfigureAwait(false); if (gitHubAccessToken == null) { logger.LogWarning( "GitHub access token disappeared during deployment, can't update to {0}!", deploymentState); return; } var gitHubClient = gitHubClientFactory.CreateClient(gitHubAccessToken); await gitHubClient .Repository .Deployment .Status .Create( compileJob.GitHubRepoId.Value, compileJob.GitHubDeploymentId.Value, new NewDeploymentStatus(deploymentState) { Description = description }) .WithToken(cancellationToken) .ConfigureAwait(false); }
async Task CheckDMApiFail(CompileJob compileJob, CancellationToken cancellationToken) { var failFile = Path.Combine(instanceClient.Metadata.Path, "Game", compileJob.DirectoryName.Value.ToString(), "A", Path.GetDirectoryName(compileJob.DmeName), "test_fail_reason.txt"); if (!File.Exists(failFile)) { return; } var text = await File.ReadAllTextAsync(failFile, cancellationToken); Assert.Fail(text); }
/// <inheritdoc /> public async Task <IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken) { logger.LogTrace("Loading compile job {0}...", compileJob.Id); var providerSubmitted = false; var newProvider = new DmbProvider(compileJob, ioManager, () => { if (providerSubmitted) { CleanJob(compileJob); } }); try { var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken); var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken); if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false))) { logger.LogWarning("Error loading compile job, .dmb missing!"); return(null); //omae wa mou shinderu } lock (this) { if (!jobLockCounts.TryGetValue(compileJob.Id, out int value)) { value = 1; jobLockCounts.Add(compileJob.Id, 1); } else { jobLockCounts[compileJob.Id] = ++value; } logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value); providerSubmitted = true; return(newProvider); } } finally { if (!providerSubmitted) { newProvider.Dispose(); } } }
/// <inheritdoc /> public async Task StartAsync(CancellationToken cancellationToken) { await Task.WhenAll(SetAutoUpdateInterval(metadata.AutoUpdateInterval.Value), Configuration.StartAsync(cancellationToken), ByondManager.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken)).ConfigureAwait(false); // dependent on so many things, its just safer this way await Watchdog.StartAsync(cancellationToken).ConfigureAwait(false); CompileJob latestCompileJob = null; await databaseContextFactory.UseContext(async db => { latestCompileJob = await db.CompileJobs.Where(x => x.Job.Instance.Id == metadata.Id).OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); }).ConfigureAwait(false); await dmbFactory.CleanUnusedCompileJobs(latestCompileJob, cancellationToken).ConfigureAwait(false); }
public static bool TryGetJobResult(int jobId, out CompileJobStatus result, out string outputFilePath) { CompileJob job = compileJobs.Find((j) => { return(j.jobId == jobId); }); if (job == null) { result = CompileJobStatus.Invalid; outputFilePath = null; return(false); } result = job.status; outputFilePath = job.path + ".dll"; return(true); }
/// <inheritdoc /> public async Task StartAsync(CancellationToken cancellationToken) { CompileJob cj = null; await databaseContextFactory.UseContext(async (db) => { cj = await db .MostRecentCompletedCompileJobOrDefault(instance, cancellationToken) .ConfigureAwait(false); }) .ConfigureAwait(false); if (cj == default(CompileJob)) { return; } await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false); // we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet }
/// <inheritdoc /> public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken) { if (job == null) { throw new ArgumentNullException(nameof(job)); } var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false); if (newProvider == null) { return; } lock (this) { nextDmbProvider?.Dispose(); nextDmbProvider = newProvider; newerDmbTcs.SetResult(nextDmbProvider); newerDmbTcs = new TaskCompletionSource <object>(); } }
public static Type CreateScriptableType(string code, string[] assemblyPaths, string typeName = "GeneratedScriptable") { CompileJob job = new CompileJob(NextJobId); compileJobs.Add(job); job.Start(code, assemblyPaths, true); CompileJobStatus result; string dllPath; if (TryGetJobResult(job.jobId, out result, out dllPath)) { if (result == CompileJobStatus.Succeeded) { Assembly assembly = Assembly.LoadFrom(dllPath); try { File.Delete(dllPath); } catch { } return(assembly.GetType(typeName)); } } return(null); }
/// <inheritdoc /> #pragma warning disable CA1506 // TODO: Decomplexify public async Task <IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken) { if (compileJob == null) { throw new ArgumentNullException(nameof(compileJob)); } // ensure we have the entire metadata tree logger.LogTrace("Loading compile job {0}...", compileJob.Id); await databaseContextFactory.UseContext( async db => compileJob = await db .CompileJobs .AsQueryable() .Where(x => x.Id == compileJob.Id) .Include(x => x.Job) .ThenInclude(x => x.StartedBy) .Include(x => x.RevisionInformation) .ThenInclude(x => x.PrimaryTestMerge) .ThenInclude(x => x.MergedBy) .Include(x => x.RevisionInformation) .ThenInclude(x => x.ActiveTestMerges) .ThenInclude(x => x.TestMerge) .ThenInclude(x => x.MergedBy) .FirstAsync(cancellationToken) .ConfigureAwait(false)) .ConfigureAwait(false); // can't wait to see that query if (!compileJob.Job.StoppedAt.HasValue) { // This happens when we're told to load the compile job that is currently finished up // It constitutes an API violation if it's returned by the DreamDaemonController so just set it here // Bit of a hack, but it works out to be nearly if not the same value that's put in the DB logger.LogTrace("Setting missing StoppedAt for CompileJob.Job #{0}...", compileJob.Job.Id); compileJob.Job.StoppedAt = DateTimeOffset.UtcNow; } var providerSubmitted = false; void CleanupAction() { if (providerSubmitted) { CleanJob(compileJob); } } var newProvider = new DmbProvider(compileJob, ioManager, CleanupAction); try { const string LegacyADirectoryName = "A"; const string LegacyBDirectoryName = "B"; var dmbExistsAtRoot = await ioManager.FileExists( ioManager.ConcatPath( newProvider.Directory, newProvider.DmbName), cancellationToken) .ConfigureAwait(false); if (!dmbExistsAtRoot) { logger.LogTrace("Didn't find .dmb at game directory root, checking A/B dirs..."); var primaryCheckTask = ioManager.FileExists( ioManager.ConcatPath( newProvider.Directory, LegacyADirectoryName, newProvider.DmbName), cancellationToken); var secondaryCheckTask = ioManager.FileExists( ioManager.ConcatPath( newProvider.Directory, LegacyBDirectoryName, newProvider.DmbName), cancellationToken); if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false))) { logger.LogWarning("Error loading compile job, .dmb missing!"); return(null); // omae wa mou shinderu } // rebuild the provider because it's using the legacy style directories // Don't dispose it logger.LogDebug("Creating legacy two folder .dmb provider targeting {0} directory...", LegacyADirectoryName); newProvider = new DmbProvider(compileJob, ioManager, CleanupAction, Path.DirectorySeparatorChar + LegacyADirectoryName); } lock (jobLockCounts) { if (!jobLockCounts.TryGetValue(compileJob.Id, out int value)) { value = 1; jobLockCounts.Add(compileJob.Id, 1); } else { jobLockCounts[compileJob.Id] = ++value; } providerSubmitted = true; logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value); return(newProvider); } } finally { if (!providerSubmitted) { newProvider.Dispose(); } } }
/// <inheritdoc /> public override Task StartDeployment( Api.Models.Internal.IGitRemoteInformation remoteInformation, CompileJob compileJob, CancellationToken cancellationToken) => Task.CompletedTask;
/// <inheritdoc /> public override Task StageDeployment(CompileJob compileJob, CancellationToken cancellationToken) => Task.CompletedTask;
/// <inheritdoc /> public override Task MarkInactive(CompileJob compileJob, CancellationToken cancellationToken) => Task.CompletedTask;
/// <inheritdoc /> public override Task FailDeployment( CompileJob compileJob, string errorMessage, CancellationToken cancellationToken) => Task.CompletedTask;
/// <inheritdoc /> public override Task ApplyDeployment( CompileJob compileJob, CompileJob oldCompileJob, CancellationToken cancellationToken) => Task.CompletedTask;
public static int QueueCompileJob(string code, string[] assemblyPaths, bool sync = false) { CompileJob job = new CompileJob(NextJobId); compileJobs.Add(job); job.Start(code, assemblyPaths, sync); return job.jobId; }
/// <inheritdoc /> #pragma warning disable CA1506 // TODO: Decomplexify public async Task <IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken) { if (compileJob == null) { throw new ArgumentNullException(nameof(compileJob)); } // ensure we have the entire compile job tree await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id) .Include(x => x.Job).ThenInclude(x => x.StartedBy) .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy) .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy) .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query logger.LogTrace("Loading compile job {0}...", compileJob.Id); var providerSubmitted = false; var newProvider = new DmbProvider(compileJob, ioManager, () => { if (providerSubmitted) { CleanJob(compileJob); } }); try { var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken); var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken); if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false))) { logger.LogWarning("Error loading compile job, .dmb missing!"); return(null); // omae wa mou shinderu } lock (this) { if (!jobLockCounts.TryGetValue(compileJob.Id, out int value)) { value = 1; jobLockCounts.Add(compileJob.Id, 1); } else { jobLockCounts[compileJob.Id] = ++value; } logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value); providerSubmitted = true; return(newProvider); } } finally { if (!providerSubmitted) { newProvider.Dispose(); } } }
public static Type CreateScriptableType(string code, string[] assemblyPaths, string typeName = "GeneratedScriptable") { CompileJob job = new CompileJob(NextJobId); compileJobs.Add(job); job.Start(code, assemblyPaths, true); CompileJobStatus result; string dllPath; if (TryGetJobResult(job.jobId, out result, out dllPath)) { if (result == CompileJobStatus.Succeeded) { Assembly assembly = Assembly.LoadFrom(dllPath); try { File.Delete(dllPath); } catch { } return assembly.GetType(typeName); } } return null; }
/// <summary> /// Construct a <see cref="TemporaryDmbProvider"/> /// </summary> /// <param name="directory">The value of <see cref="Directory"/></param> /// <param name="dmb">The value of <see cref="DmbName"/></param> /// <param name="compileJob">The value of <see cref="CompileJob"/></param> public TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob) { DmbName = dmb ?? throw new ArgumentNullException(nameof(dmb)); Directory = directory ?? throw new ArgumentNullException(nameof(directory)); CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob)); }