@@ -38,9 +38,14 @@ public ArchLoader LoadAssemblies(params Assembly[] assemblies)
3838 }
3939
4040 public ArchLoader LoadAssembliesIncludingDependencies ( params Assembly [ ] assemblies )
41+ {
42+ return LoadAssembliesIncludingDependencies ( assemblies , false ) ;
43+ }
44+
45+ public ArchLoader LoadAssembliesIncludingDependencies ( IEnumerable < Assembly > assemblies , bool recursive )
4146 {
4247 var assemblySet = new HashSet < Assembly > ( assemblies ) ;
43- assemblySet . ForEach ( assembly => LoadAssemblyIncludingDependencies ( assembly ) ) ;
48+ assemblySet . ForEach ( assembly => LoadAssemblyIncludingDependencies ( assembly , recursive ) ) ;
4449 return this ;
4550 }
4651
@@ -53,10 +58,11 @@ public ArchLoader LoadFilteredDirectory(string directory, string filter,
5358
5459 var result = this ;
5560 return assemblies . Aggregate ( result ,
56- ( current , assembly ) => current . LoadAssembly ( assembly , false ) ) ;
61+ ( current , assembly ) => current . LoadAssembly ( assembly , false , false ) ) ;
5762 }
5863
5964 public ArchLoader LoadFilteredDirectoryIncludingDependencies ( string directory , string filter ,
65+ bool recursive = false ,
6066 SearchOption searchOption = TopDirectoryOnly )
6167 {
6268 var path = Path . GetFullPath ( directory ) ;
@@ -65,73 +71,107 @@ public ArchLoader LoadFilteredDirectoryIncludingDependencies(string directory, s
6571
6672 var result = this ;
6773 return assemblies . Aggregate ( result ,
68- ( current , assembly ) => current . LoadAssembly ( assembly , true ) ) ;
74+ ( current , assembly ) => current . LoadAssembly ( assembly , true , recursive ) ) ;
6975 }
7076
7177 public ArchLoader LoadNamespacesWithinAssembly ( Assembly assembly , params string [ ] namespc )
7278 {
7379 var nameSpaces = new HashSet < string > ( namespc ) ;
74- nameSpaces . ForEach ( nameSpace => { LoadModule ( assembly . Location , nameSpace , false ) ; } ) ;
80+ nameSpaces . ForEach ( nameSpace => { LoadModule ( assembly . Location , nameSpace , false , false ) ; } ) ;
7581 return this ;
7682 }
7783
7884 public ArchLoader LoadAssembly ( Assembly assembly )
7985 {
80- return LoadAssembly ( assembly . Location , false ) ;
86+ return LoadAssembly ( assembly . Location , false , false ) ;
8187 }
8288
83- public ArchLoader LoadAssemblyIncludingDependencies ( Assembly assembly )
89+ public ArchLoader LoadAssemblyIncludingDependencies ( Assembly assembly , bool recursive = false )
8490 {
85- return LoadAssembly ( assembly . Location , true ) ;
91+ return LoadAssembly ( assembly . Location , true , recursive ) ;
8692 }
8793
88- private ArchLoader LoadAssembly ( string fileName , bool includeDependencies )
94+ private ArchLoader LoadAssembly ( string fileName , bool includeDependencies , bool recursive )
8995 {
90- LoadModule ( fileName , null , includeDependencies ) ;
96+ LoadModule ( fileName , null , includeDependencies , recursive ) ;
9197
9298 return this ;
9399 }
94100
95- private void LoadModule ( string fileName , string nameSpace , bool includeDependencies )
101+ private void LoadModule ( string fileName , string nameSpace , bool includeDependencies , bool recursive )
96102 {
97103 try
98104 {
99105 var module = ModuleDefinition . ReadModule ( fileName ,
100- new ReaderParameters { AssemblyResolver = _assemblyResolver } ) ;
106+ new ReaderParameters { AssemblyResolver = _assemblyResolver } ) ;
107+ var processedAssemblies = new List < AssemblyNameReference > { module . Assembly . Name } ;
108+ var resolvedModules = new List < ModuleDefinition > ( ) ;
101109 _assemblyResolver . AddLib ( module . Assembly ) ;
102110 _archBuilder . AddAssembly ( module . Assembly , false ) ;
103111 foreach ( var assemblyReference in module . AssemblyReferences )
104112 {
105- try
113+ if ( includeDependencies && recursive )
106114 {
107- _assemblyResolver . AddLib ( assemblyReference ) ;
108- if ( includeDependencies )
109- {
110- _archBuilder . AddAssembly (
111- _assemblyResolver . Resolve ( assemblyReference ) ??
112- throw new AssemblyResolutionException ( assemblyReference ) , false ) ;
113- }
115+ AddReferencedAssembliesRecursively ( assemblyReference , processedAssemblies , resolvedModules ) ;
114116 }
115- catch ( AssemblyResolutionException )
117+ else
116118 {
117- //Failed to resolve assembly, skip it
119+ try
120+ {
121+ processedAssemblies . Add ( assemblyReference ) ;
122+ _assemblyResolver . AddLib ( assemblyReference ) ;
123+ if ( includeDependencies )
124+ {
125+ var assemblyDefinition = _assemblyResolver . Resolve ( assemblyReference ) ??
126+ throw new AssemblyResolutionException ( assemblyReference ) ;
127+ _archBuilder . AddAssembly ( assemblyDefinition , false ) ;
128+ resolvedModules . AddRange ( assemblyDefinition . Modules ) ;
129+ }
130+ }
131+ catch ( AssemblyResolutionException )
132+ {
133+ //Failed to resolve assembly, skip it
134+ }
118135 }
119136 }
120137
121138 _archBuilder . LoadTypesForModule ( module , nameSpace ) ;
122- if ( includeDependencies )
139+ foreach ( var moduleDefinition in resolvedModules )
123140 {
124- foreach ( var moduleDefinition in module . AssemblyReferences . SelectMany ( reference =>
125- _assemblyResolver . Resolve ( reference ) ? . Modules ) )
126- {
127- _archBuilder . LoadTypesForModule ( moduleDefinition , null ) ;
128- }
141+ _archBuilder . LoadTypesForModule ( moduleDefinition , null ) ;
129142 }
130143 }
131144 catch ( BadImageFormatException )
132145 {
133146 // invalid file format of DLL or executable, therefore ignored
134147 }
135148 }
149+
150+ private void AddReferencedAssembliesRecursively ( AssemblyNameReference currentAssemblyReference ,
151+ ICollection < AssemblyNameReference > processedAssemblies , List < ModuleDefinition > resolvedModules )
152+ {
153+ if ( processedAssemblies . Contains ( currentAssemblyReference ) )
154+ {
155+ return ;
156+ }
157+
158+ processedAssemblies . Add ( currentAssemblyReference ) ;
159+ try
160+ {
161+ _assemblyResolver . AddLib ( currentAssemblyReference ) ;
162+ var assemblyDefinition = _assemblyResolver . Resolve ( currentAssemblyReference ) ??
163+ throw new AssemblyResolutionException ( currentAssemblyReference ) ;
164+ _archBuilder . AddAssembly ( assemblyDefinition , false ) ;
165+ resolvedModules . AddRange ( assemblyDefinition . Modules ) ;
166+ foreach ( var reference in assemblyDefinition . Modules . SelectMany ( m => m . AssemblyReferences ) )
167+ {
168+ AddReferencedAssembliesRecursively ( reference , processedAssemblies , resolvedModules ) ;
169+ }
170+ }
171+ catch ( AssemblyResolutionException )
172+ {
173+ //Failed to resolve assembly, skip it
174+ }
175+ }
136176 }
137177}
0 commit comments