Skip to content

Commit 274037f

Browse files
authored
Merge pull request #172 from mono/opt-out-alc
Add host option to disable AssemblyLoadContext
2 parents 2257e9e + 79ec659 commit 274037f

File tree

5 files changed

+60
-19
lines changed

5 files changed

+60
-19
lines changed

Mono.TextTemplating/Mono.TextTemplating.CodeCompilation/CompiledAssemblyData.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public Assembly LoadInAssemblyLoadContext (AssemblyLoadContext loadContext)
3838
return loadContext.LoadFromStream (new MemoryStream (Assembly));
3939
}
4040
}
41-
#else
41+
#endif
4242
public Assembly LoadInCurrentAppDomain ()
4343
{
4444
if (DebugSymbols != null) {
@@ -47,6 +47,5 @@ public Assembly LoadInCurrentAppDomain ()
4747
return System.Reflection.Assembly.Load (Assembly);
4848
}
4949
}
50-
#endif
5150
}
5251
}

Mono.TextTemplating/Mono.TextTemplating/CompiledTemplate.TemplateAssemblyContext.cs

+42-12
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,51 @@ namespace Mono.TextTemplating;
1111

1212
partial class CompiledTemplate
1313
{
14-
[SuppressMessage ("Performance", "CA1822:Mark members as static", Justification = "Same API for ALC and AppDomain build variants of the class")]
15-
sealed class TemplateAssemblyContext : IDisposable
14+
/// <summary>
15+
/// Abstracts over loading assemblies into an AssemblyLoadContext or AppDomain
16+
/// and resolving assemblies from the host.
17+
/// </summary>
18+
abstract class TemplateAssemblyContext : IDisposable
1619
{
20+
public abstract Assembly LoadAssemblyFile (string assemblyPath);
21+
public abstract Assembly LoadInMemoryAssembly (CompiledAssemblyData assemblyData);
22+
public virtual void Dispose () { }
23+
24+
[SuppressMessage ("Performance", "CA1859:Use concrete types when possible for improved performance", Justification = "Conditionally compiled version of this returns multiple concrete types")]
25+
26+
public static TemplateAssemblyContext Create (ITextTemplatingEngineHost host, string[] referenceAssemblyFiles)
27+
{
28+
#if FEATURE_ASSEMBLY_LOAD_CONTEXT
29+
if (!host.IsAssemblyLoadContextDisabled ()) {
30+
return new AssemblyLoadContextTemplateAssemblyContext (host, referenceAssemblyFiles);
31+
}
32+
#endif
33+
return new CurrentAppDomainTemplateAssemblyContext (host, referenceAssemblyFiles);
34+
}
35+
}
36+
1737
#if FEATURE_ASSEMBLY_LOAD_CONTEXT
38+
sealed class AssemblyLoadContextTemplateAssemblyContext : TemplateAssemblyContext
39+
{
1840
readonly TemplateAssemblyLoadContext templateContext;
19-
public TemplateAssemblyContext (ITextTemplatingEngineHost host, string[] referenceAssemblyFiles) => templateContext = new (referenceAssemblyFiles, host);
20-
public Assembly LoadAssemblyFile (string assemblyPath) => templateContext.LoadFromAssemblyPath (assemblyPath);
21-
public Assembly LoadInMemoryAssembly (CompiledAssemblyData assemblyData) => assemblyData.LoadInAssemblyLoadContext (templateContext);
22-
public void Dispose () { }
23-
#else
24-
readonly CurrentDomainAssemblyResolver assemblyResolver;
25-
public TemplateAssemblyContext (ITextTemplatingEngineHost host, string[] referenceAssemblyFiles) => assemblyResolver = new (referenceAssemblyFiles, host.ResolveAssemblyReference);
26-
public Assembly LoadAssemblyFile (string assemblyPath) => Assembly.LoadFile (assemblyPath);
27-
public Assembly LoadInMemoryAssembly (CompiledAssemblyData assemblyData) => assemblyData.LoadInCurrentAppDomain ();
28-
public void Dispose () => assemblyResolver.Dispose ();
41+
public AssemblyLoadContextTemplateAssemblyContext (ITextTemplatingEngineHost host, string[] referenceAssemblyFiles)
42+
=> templateContext = new (referenceAssemblyFiles, host);
43+
public override Assembly LoadAssemblyFile (string assemblyPath) => templateContext.LoadFromAssemblyPath (assemblyPath);
44+
public override Assembly LoadInMemoryAssembly (CompiledAssemblyData assemblyData) => assemblyData.LoadInAssemblyLoadContext (templateContext);
45+
}
2946
#endif
47+
48+
sealed class CurrentAppDomainTemplateAssemblyContext : TemplateAssemblyContext
49+
{
50+
readonly CurrentDomainAssemblyResolver assemblyResolver;
51+
public CurrentAppDomainTemplateAssemblyContext (ITextTemplatingEngineHost host, string[] referenceAssemblyFiles)
52+
=> assemblyResolver = new (referenceAssemblyFiles, host.ResolveAssemblyReference);
53+
public override Assembly LoadAssemblyFile (string assemblyPath) => Assembly.LoadFile (assemblyPath);
54+
public override Assembly LoadInMemoryAssembly (CompiledAssemblyData assemblyData) => assemblyData.LoadInCurrentAppDomain ();
55+
public override void Dispose ()
56+
{
57+
base.Dispose ();
58+
assemblyResolver.Dispose ();
59+
}
3060
}
3161
}

Mono.TextTemplating/Mono.TextTemplating/CompiledTemplate.TemplateExecutor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class TemplateProcessor : MarshalByRefObject
1919
[SuppressMessage ("Performance", "CA1822:Mark members as static", Justification = "Needs to be an instance for MarshalByRefObject")]
2020
public string CreateAndProcess (ITextTemplatingEngineHost host, CompiledAssemblyData templateAssemblyData, string templateAssemblyFile, string fullName, CultureInfo culture, string[] referencedAssemblyFiles)
2121
{
22-
using var context = new TemplateAssemblyContext (host, referencedAssemblyFiles);
22+
using var context = TemplateAssemblyContext.Create (host, referencedAssemblyFiles);
2323

2424
Assembly assembly = templateAssemblyData is not null
2525
? context.LoadInMemoryAssembly (templateAssemblyData)

Mono.TextTemplating/Mono.TextTemplating/CurrentDomainAssemblyResolver.cs

-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4-
#if !FEATURE_ASSEMBLY_LOAD_CONTEXT
5-
64
using System;
75
using System.IO;
86
using System.Reflection;
@@ -52,5 +50,3 @@ public void Dispose ()
5250
}
5351
}
5452
}
55-
56-
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using Microsoft.VisualStudio.TextTemplating;
6+
7+
static class HostOptionExtensions
8+
{
9+
const string DisableAlcOptionName = "DisableAssemblyLoadContext";
10+
11+
static bool IsOptionTrue (this ITextTemplatingEngineHost host, string optionName) =>
12+
host.GetHostOption(optionName) is string optionVal
13+
&& (optionVal == "1" || optionVal.Equals("true", StringComparison.OrdinalIgnoreCase));
14+
15+
public static bool IsAssemblyLoadContextDisabled (this ITextTemplatingEngineHost host) => host.IsOptionTrue (DisableAlcOptionName);
16+
}

0 commit comments

Comments
 (0)