Skip to content

Commit

Permalink
Merge pull request #134 from daviddotcs/cancellation-token-overloads
Browse files Browse the repository at this point in the history
Add CancellationToken overloads to Compile methods
  • Loading branch information
adoconnection authored Nov 17, 2023
2 parents 3a41c59 + b6c9f6e commit 3ed53cf
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 18 deletions.
61 changes: 61 additions & 0 deletions RazorEngineCore.Tests/TestCompileAndRun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace RazorEngineCore.Tests
{
using System.Runtime.InteropServices;
using System.Threading;

[TestClass]
public class TestCompileAndRun
Expand Down Expand Up @@ -728,6 +729,66 @@ @using TestAssembly
Assert.AreEqual(expected, actual);
}

[TestMethod]
public void TestCompileCancellation_DynamicModel()
{
RazorEngine razorEngine = new RazorEngine();
using (CancellationTokenSource cancellationSource = new CancellationTokenSource())
{
cancellationSource.Cancel();

Assert.ThrowsException<OperationCanceledException>(() =>
{
IRazorEngineCompiledTemplate template = razorEngine.Compile("Hello @Model.Name", cancellationToken: cancellationSource.Token);
});
}
}

[TestMethod]
public async Task TestCompileCancellation_DynamicModelAsync()
{
RazorEngine razorEngine = new RazorEngine();
using (CancellationTokenSource cancellationSource = new CancellationTokenSource())
{
cancellationSource.Cancel();

await Assert.ThrowsExceptionAsync<OperationCanceledException>(async () =>
{
IRazorEngineCompiledTemplate template = await razorEngine.CompileAsync("Hello @Model.Name", cancellationToken: cancellationSource.Token);
});
}
}

[TestMethod]
public void TestCompileCancellation_TypedModel1()
{
RazorEngine razorEngine = new RazorEngine();
using (CancellationTokenSource cancellationSource = new CancellationTokenSource())
{
cancellationSource.Cancel();

Assert.ThrowsException<OperationCanceledException>(() =>
{
IRazorEngineCompiledTemplate<TestTemplate1> template = razorEngine.Compile<TestTemplate1>("Hello @A @B @(A + B) @C @Decorator(\"777\")", cancellationToken: cancellationSource.Token);
});
}
}

[TestMethod]
public async Task TestCompileCancellation_TypedModel1Async()
{
RazorEngine razorEngine = new RazorEngine();
using (CancellationTokenSource cancellationSource = new CancellationTokenSource())
{
cancellationSource.Cancel();

await Assert.ThrowsExceptionAsync<OperationCanceledException>(async () =>
{
IRazorEngineCompiledTemplate<TestTemplate1> template = await razorEngine.CompileAsync<TestTemplate1>("Hello @A @B @(A + B) @C @Decorator(\"777\")", cancellationToken: cancellationSource.Token);
});
}
}

private static List<MetadataReference> GetMetadataReferences()
{
if (RuntimeInformation.FrameworkDescription.StartsWith(
Expand Down
11 changes: 6 additions & 5 deletions RazorEngineCore/IRazorEngine.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace RazorEngineCore
{
public interface IRazorEngine
{
IRazorEngineCompiledTemplate<T> Compile<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null)
IRazorEngineCompiledTemplate<T> Compile<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default)
where T : IRazorEngineTemplate;
Task<IRazorEngineCompiledTemplate<T>> CompileAsync<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null)

Task<IRazorEngineCompiledTemplate<T>> CompileAsync<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default)
where T : IRazorEngineTemplate;

IRazorEngineCompiledTemplate Compile(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null);
IRazorEngineCompiledTemplate Compile(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default);

Task<IRazorEngineCompiledTemplate> CompileAsync(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null);
Task<IRazorEngineCompiledTemplate> CompileAsync(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default);
}
}
29 changes: 16 additions & 13 deletions RazorEngineCore/RazorEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
Expand All @@ -15,41 +16,42 @@ namespace RazorEngineCore
{
public class RazorEngine : IRazorEngine
{
public IRazorEngineCompiledTemplate<T> Compile<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null) where T : IRazorEngineTemplate
public IRazorEngineCompiledTemplate<T> Compile<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default) where T : IRazorEngineTemplate
{
IRazorEngineCompilationOptionsBuilder compilationOptionsBuilder = new RazorEngineCompilationOptionsBuilder();
compilationOptionsBuilder.AddAssemblyReference(typeof(T).Assembly);
compilationOptionsBuilder.Inherits(typeof(T));

builderAction?.Invoke(compilationOptionsBuilder);

RazorEngineCompiledTemplateMeta meta = this.CreateAndCompileToStream(content, compilationOptionsBuilder.Options);
MemoryStream memoryStream = this.CreateAndCompileToStream(content, compilationOptionsBuilder.Options, cancellationToken);

return new RazorEngineCompiledTemplate<T>(meta);
}

public Task<IRazorEngineCompiledTemplate<T>> CompileAsync<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null) where T : IRazorEngineTemplate
public Task<IRazorEngineCompiledTemplate<T>> CompileAsync<T>(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default) where T : IRazorEngineTemplate
{
return Task.Factory.StartNew(() => this.Compile<T>(content: content, builderAction: builderAction));
return Task.Factory.StartNew(() => this.Compile<T>(content: content, builderAction: builderAction, cancellationToken: cancellationToken));
}

public IRazorEngineCompiledTemplate Compile(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null)
public IRazorEngineCompiledTemplate Compile(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default)
{
IRazorEngineCompilationOptionsBuilder compilationOptionsBuilder = new RazorEngineCompilationOptionsBuilder();
compilationOptionsBuilder.Inherits(typeof(RazorEngineTemplateBase));

builderAction?.Invoke(compilationOptionsBuilder);
RazorEngineCompiledTemplateMeta meta = this.CreateAndCompileToStream(content, compilationOptionsBuilder.Options);

RazorEngineCompiledTemplateMeta meta = this.CreateAndCompileToStream(content, compilationOptionsBuilder.Options, cancellationToken);
return new RazorEngineCompiledTemplate(meta);
}

public Task<IRazorEngineCompiledTemplate> CompileAsync(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null)
public Task<IRazorEngineCompiledTemplate> CompileAsync(string content, Action<IRazorEngineCompilationOptionsBuilder> builderAction = null, CancellationToken cancellationToken = default)
{
return Task.Factory.StartNew(() => this.Compile(content: content, builderAction: builderAction));
return Task.Factory.StartNew(() => this.Compile(content: content, builderAction: builderAction, cancellationToken: cancellationToken));
}

protected virtual RazorEngineCompiledTemplateMeta CreateAndCompileToStream(string templateSource, RazorEngineCompilationOptions options)
protected virtual RazorEngineCompiledTemplateMeta CreateAndCompileToStream(string templateSource, RazorEngineCompilationOptions options, CancellationToken cancellationToken)

{
templateSource = this.WriteDirectives(templateSource, options);
string projectPath = @".";
Expand All @@ -75,9 +77,9 @@ protected virtual RazorEngineCompiledTemplateMeta CreateAndCompileToStream(strin
new List<TagHelperDescriptor>());



RazorCSharpDocument razorCSharpDocument = codeDocument.GetCSharpDocument();
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(razorCSharpDocument.GeneratedCode);
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(razorCSharpDocument.GeneratedCode, cancellationToken: cancellationToken);


CSharpCompilation compilation = CSharpCompilation.Create(
fileName,
Expand Down Expand Up @@ -110,7 +112,8 @@ protected virtual RazorEngineCompiledTemplateMeta CreateAndCompileToStream(strin
MemoryStream assemblyStream = new MemoryStream();
MemoryStream pdbStream = options.IncludeDebuggingInfo ? new MemoryStream() : null;

EmitResult emitResult = compilation.Emit(assemblyStream, pdbStream);
EmitResult emitResult = compilation.Emit(assemblyStream, pdbStream, cancellationToken: cancellationToken);


if (!emitResult.Success)
{
Expand Down

0 comments on commit 3ed53cf

Please sign in to comment.