Skip to content

Commit 50d0ed7

Browse files
committed
Add support for loading assemblies through MetadataReference
1 parent a88c8bf commit 50d0ed7

File tree

5 files changed

+76
-1
lines changed

5 files changed

+76
-1
lines changed

RazorEngineCore.Tests/TestCompileAndRun.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Reflection;
15
using System.Threading.Tasks;
6+
using Microsoft.CodeAnalysis;
7+
using Microsoft.CodeAnalysis.CSharp;
8+
using Microsoft.CodeAnalysis.Emit;
29
using Microsoft.VisualStudio.TestTools.UnitTesting;
310
using RazorEngineCore.Tests.Models;
411

@@ -454,5 +461,61 @@ public async Task TestCompileAndRun_LinqAsync()
454461

455462
Assert.AreEqual(expected, actual);
456463
}
464+
465+
[TestMethod]
466+
public async Task TestCompileAndRun_MetadataReference()
467+
{
468+
string greetingClass = @"
469+
namespace TestAssembly
470+
{
471+
public static class Greeting
472+
{
473+
public static string GetGreeting(string name)
474+
{
475+
return ""Hello, "" + name + ""!"";
476+
}
477+
}
478+
}
479+
";
480+
481+
RazorEngine razorEngine = new RazorEngine();
482+
IRazorEngineCompiledTemplate template = await razorEngine.CompileAsync(@"
483+
@using TestAssembly
484+
<p>@Greeting.GetGreeting(""Name"")</p>
485+
", builder =>
486+
{
487+
// This needs to be done in the builder to have access to all of the assemblies added through
488+
// the various AddAssemblyReference options
489+
CSharpCompilation compilation = CSharpCompilation.Create(
490+
"TestAssembly",
491+
new []
492+
{
493+
CSharpSyntaxTree.ParseText(greetingClass)
494+
},
495+
builder.Options.ReferencedAssemblies
496+
.Select(ass => MetadataReference.CreateFromFile(ass.Location)).ToList(),
497+
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
498+
);
499+
MemoryStream memoryStream = new MemoryStream();
500+
EmitResult emitResult = compilation.Emit(memoryStream);
501+
if (!emitResult.Success) return;
502+
503+
memoryStream.Position = 0;
504+
builder.AddMetadataReference(MetadataReference.CreateFromStream(memoryStream));
505+
506+
// Add an assembly resolver so the assembly can be found
507+
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
508+
new AssemblyName(eventArgs.Name ?? string.Empty).Name == "TestAssembly"
509+
? Assembly.Load(memoryStream.ToArray())
510+
: null;
511+
});
512+
513+
string expected = @"
514+
<p>Hello, Name!</p>
515+
";
516+
string actual = await template.RunAsync();
517+
518+
Assert.AreEqual(expected, actual);
519+
}
457520
}
458521
}

RazorEngineCore/IRazorEngineCompilationOptionsBuilder.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Reflection;
3+
using Microsoft.CodeAnalysis;
34

45
namespace RazorEngineCore
56
{
@@ -12,6 +13,8 @@ public interface IRazorEngineCompilationOptionsBuilder
1213
void AddAssemblyReference(Assembly assembly);
1314

1415
void AddAssemblyReference(Type type);
16+
17+
void AddMetadataReference(MetadataReference reference);
1518

1619
void AddUsing(string namespaceName);
1720

RazorEngineCore/RazorEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ private MemoryStream CreateAndCompileToStream(string templateSource, RazorEngine
8383
},
8484
options.ReferencedAssemblies
8585
.Select(ass => MetadataReference.CreateFromFile(ass.Location))
86-
.ToList(),
86+
.Concat(options.MetadataReferences).ToList(),
8787
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
8888

8989
MemoryStream memoryStream = new MemoryStream();

RazorEngineCore/RazorEngineCompilationOptions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Reflection;
3+
using Microsoft.CodeAnalysis;
34

45
namespace RazorEngineCore
56
{
@@ -16,6 +17,8 @@ public class RazorEngineCompilationOptions
1617
Assembly.Load(new AssemblyName("System.Linq.Expressions"))
1718
};
1819

20+
public HashSet<MetadataReference> MetadataReferences { get; set; } = new HashSet<MetadataReference>();
21+
1922
public string TemplateNamespace { get; set; } = "TemplateNamespace";
2023
public string Inherits { get; set; } = "RazorEngineCore.RazorEngineTemplateBase";
2124

RazorEngineCore/RazorEngineCompilationOptionsBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq;
33
using System.Reflection;
4+
using Microsoft.CodeAnalysis;
45

56
namespace RazorEngineCore
67
{
@@ -34,6 +35,11 @@ public void AddAssemblyReference(Type type)
3435
}
3536
}
3637

38+
public void AddMetadataReference(MetadataReference reference)
39+
{
40+
this.Options.MetadataReferences.Add(reference);
41+
}
42+
3743
public void AddUsing(string namespaceName)
3844
{
3945
this.Options.DefaultUsings.Add(namespaceName);

0 commit comments

Comments
 (0)