@@ -7,6 +7,8 @@ namespace CodeGeneration.Roslyn
77 using Microsoft . CodeAnalysis . CSharp ;
88 using Microsoft . CodeAnalysis . CSharp . Syntax ;
99 using Microsoft . CodeAnalysis . Text ;
10+ using Microsoft . Extensions . DependencyModel ;
11+ using Microsoft . Extensions . DependencyModel . Resolution ;
1012 using System ;
1113 using System . Collections . Generic ;
1214 using System . Globalization ;
@@ -29,6 +31,10 @@ public class CompilationGenerator
2931 private readonly List < string > generatedFiles = new List < string > ( ) ;
3032 private readonly List < string > additionalWrittenFiles = new List < string > ( ) ;
3133 private readonly List < string > loadedAssemblies = new List < string > ( ) ;
34+ private readonly Dictionary < string , Assembly > assembliesByPath = new Dictionary < string , Assembly > ( ) ;
35+ private readonly HashSet < string > directoriesWithResolver = new HashSet < string > ( ) ;
36+ private CompositeCompilationAssemblyResolver assemblyResolver ;
37+ private DependencyContext dependencyContext ;
3238
3339 /// <summary>
3440 /// Gets or sets the list of paths of files to be compiled.
@@ -67,6 +73,19 @@ public class CompilationGenerator
6773
6874 public string ProjectDirectory { get ; set ; }
6975
76+ public CompilationGenerator ( )
77+ {
78+ this . assemblyResolver = new CompositeCompilationAssemblyResolver ( new ICompilationAssemblyResolver [ ]
79+ {
80+ new ReferenceAssemblyPathResolver ( ) ,
81+ new PackageCompilationAssemblyResolver ( )
82+ } ) ;
83+ this . dependencyContext = DependencyContext . Default ;
84+
85+ var loadContext = AssemblyLoadContext . GetLoadContext ( this . GetType ( ) . GetTypeInfo ( ) . Assembly ) ;
86+ loadContext . Resolving += this . ResolveAssembly ;
87+ }
88+
7089 public void Generate ( IProgress < Diagnostic > progress = null , CancellationToken cancellationToken = default ( CancellationToken ) )
7190 {
7291 Verify . Operation ( this . Compile != null , $ "{ nameof ( Compile ) } must be set first.") ;
@@ -159,8 +178,45 @@ public class CompilationGenerator
159178
160179 protected virtual Assembly LoadAssembly ( string path )
161180 {
181+ if ( this . assembliesByPath . ContainsKey ( path ) )
182+ return this . assembliesByPath [ path ] ;
183+
162184 var loadContext = AssemblyLoadContext . GetLoadContext ( this . GetType ( ) . GetTypeInfo ( ) . Assembly ) ;
163- return loadContext . LoadFromAssemblyPath ( path ) ;
185+ var assembly = loadContext . LoadFromAssemblyPath ( path ) ;
186+
187+ this . dependencyContext = this . dependencyContext . Merge ( DependencyContext . Load ( assembly ) ) ;
188+ var basePath = Path . GetDirectoryName ( path ) ;
189+ if ( ! this . directoriesWithResolver . Contains ( basePath ) )
190+ {
191+ this . assemblyResolver = new CompositeCompilationAssemblyResolver ( new ICompilationAssemblyResolver [ ]
192+ {
193+ new AppBaseCompilationAssemblyResolver ( basePath ) ,
194+ this . assemblyResolver
195+ } ) ;
196+ }
197+
198+ this . assembliesByPath . Add ( path , assembly ) ;
199+ return assembly ;
200+ }
201+
202+ private Assembly ResolveAssembly ( AssemblyLoadContext context , AssemblyName name )
203+ {
204+ var library = this . dependencyContext . RuntimeLibraries . FirstOrDefault ( runtime => string . Equals ( runtime . Name , name . Name , StringComparison . OrdinalIgnoreCase ) ) ;
205+ if ( library == null )
206+ return null ;
207+ var wrapper = new CompilationLibrary (
208+ library . Type ,
209+ library . Name ,
210+ library . Version ,
211+ library . Hash ,
212+ library . RuntimeAssemblyGroups . SelectMany ( g => g . AssetPaths ) ,
213+ library . Dependencies ,
214+ library . Serviceable ) ;
215+
216+ var assemblyPathes = new List < string > ( ) ;
217+ this . assemblyResolver . TryResolveAssemblyPaths ( wrapper , assemblyPathes ) ;
218+
219+ return assemblyPathes . Select ( context . LoadFromAssemblyPath ) . FirstOrDefault ( ) ;
164220 }
165221
166222 private static DateTime GetLastModifiedAssemblyTime ( string assemblyListPath )
0 commit comments