1212
1313 public abstract class ContextAwareTask : Task
1414 {
15+ #if NETCOREAPP2_0
16+ /// <summary>
17+ /// Our custom <see cref="AssemblyLoadContext"/> that we create to host our Task.
18+ /// </summary>
19+ /// <remarks>
20+ /// We only create *one* of these, and reuse it for subsequent task invocations,
21+ /// because creating multiple of them hit https://github.com/dotnet/coreclr/issues/19654
22+ /// </remarks>
23+ private static CustomAssemblyLoader Loader;
24+ #endif
25+
1526 protected virtual string ManagedDllDirectory => Path.GetDirectoryName(new Uri(this.GetType().GetTypeInfo().Assembly.CodeBase).LocalPath);
1627
1728 protected virtual string UnmanagedDllDirectory => null;
@@ -20,8 +31,13 @@ public override bool Execute()
2031 {
2132#if NETCOREAPP2_0
2233 string taskAssemblyPath = new Uri(this.GetType().GetTypeInfo().Assembly.CodeBase).LocalPath;
23- var ctxt = new CustomAssemblyLoader(this);
24- Assembly inContextAssembly = ctxt.LoadFromAssemblyPath(taskAssemblyPath);
34+ if (Loader == null)
35+ {
36+ Loader = new CustomAssemblyLoader();
37+ }
38+
39+ Loader.LoaderTask = this;
40+ Assembly inContextAssembly = Loader.LoadFromAssemblyPath(taskAssemblyPath);
2541 Type innerTaskType = inContextAssembly.GetType(this.GetType().FullName);
2642 object innerTask = Activator.CreateInstance(innerTaskType);
2743
@@ -71,31 +87,41 @@ public override bool Execute()
7187#if NETCOREAPP2_0
7288 private class CustomAssemblyLoader : AssemblyLoadContext
7389 {
74- private readonly ContextAwareTask loaderTask;
90+ private ContextAwareTask loaderTask;
7591
76- internal CustomAssemblyLoader(ContextAwareTask loaderTask )
92+ internal CustomAssemblyLoader()
7793 {
78- this.loaderTask = loaderTask;
94+ }
95+
96+ internal ContextAwareTask LoaderTask
97+ {
98+ get => this.loaderTask;
99+ set => this.loaderTask = value;
79100 }
80101
81102 protected override Assembly Load(AssemblyName assemblyName)
82103 {
83- // Always load libgit2sharp in the default context.
84- // Something about the p/invoke done in that library with its custom marshaler
85- // doesn't sit well with Core CLR 2.x.
86- // See https://github.com/AArnott/Nerdbank.GitVersioning/issues/215 and https://github.com/dotnet/coreclr/issues/19654
87- AssemblyLoadContext preferredContext = assemblyName.Name.Equals("libgit2sharp", StringComparison.OrdinalIgnoreCase) ? Default : this;
104+ if (this.loaderTask == null)
105+ {
106+ throw new InvalidOperationException(nameof(this.loaderTask) + " must be set first.");
107+ }
108+
88109 string assemblyPath = Path.Combine(this.loaderTask.ManagedDllDirectory, assemblyName.Name) + ".dll";
89110 if (File.Exists(assemblyPath))
90111 {
91- return preferredContext .LoadFromAssemblyPath(assemblyPath);
112+ return this .LoadFromAssemblyPath(assemblyPath);
92113 }
93114
94115 return Default.LoadFromAssemblyName(assemblyName);
95116 }
96117
97118 protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
98119 {
120+ if (this.loaderTask == null)
121+ {
122+ throw new InvalidOperationException(nameof(this.loaderTask) + " must be set first.");
123+ }
124+
99125 string unmanagedDllPath = Directory.EnumerateFiles(
100126 this.loaderTask.UnmanagedDllDirectory,
101127 $"{unmanagedDllName}.*").Concat(
0 commit comments