1010
1111namespace BepInEx . Bootstrap ;
1212
13- internal class CachedPluginLoadContext : IPluginLoadContext , IDisposable
14- {
15- public IPluginLoadContext PluginLoadContext { get ; }
16- private byte [ ] assemblyData ;
17- private byte [ ] assemblySymbolsData ;
18-
19- public CachedPluginLoadContext ( IPluginLoadContext pluginLoadContext )
20- {
21- PluginLoadContext = pluginLoadContext ;
22- }
23-
24- public string AssemblyIdentifier => PluginLoadContext . AssemblyIdentifier ;
25- public string AssemblyHash => PluginLoadContext . AssemblyHash ;
26- public byte [ ] GetAssemblyData ( )
27- {
28- return assemblyData ??= PluginLoadContext . GetAssemblyData ( ) ;
29- }
30-
31- public byte [ ] GetAssemblySymbolsData ( )
32- {
33- return assemblySymbolsData ??= PluginLoadContext . GetAssemblySymbolsData ( ) ;
34- }
35-
36- public byte [ ] GetFile ( string relativePath )
37- {
38- return PluginLoadContext . GetFile ( relativePath ) ;
39- }
40-
41- public void Dispose ( )
42- {
43- assemblyData = null ;
44- assemblySymbolsData = null ;
45- }
46- }
47-
4813/// <summary>
4914/// A cacheable metadata item. Can be used with <see cref="TypeLoader.LoadAssemblyCache{T}" /> and
5015/// <see cref="TypeLoader.SaveAssemblyCache{T}" /> to cache plugin metadata.
@@ -70,11 +35,6 @@ public interface ICacheable
7035/// <typeparam name="T"></typeparam>
7136public class CachedAssembly < T > where T : ICacheable
7237{
73- /// <summary>
74- /// The version of the cache which increments on each format changes
75- /// </summary>
76- public const int Version = 0 ;
77-
7838 /// <summary>
7939 /// List of cached items inside the assembly.
8040 /// </summary>
@@ -129,9 +89,7 @@ public static AssemblyDefinition CecilResolveOnFailure(object sender, AssemblyNa
12989 {
13090 Paths . BepInExAssemblyDirectory ,
13191 Paths . PluginPath ,
132- Paths . PluginProviderPath ,
13392 Paths . PatcherPluginPath ,
134- Paths . PatcherProviderPath ,
13593 Paths . ManagedPath
13694 } . Concat ( SearchDirectories ) ;
13795
@@ -168,8 +126,9 @@ public static AssemblyDefinition CecilResolveOnFailure(object sender, AssemblyNa
168126 /// selector.
169127 /// </returns>
170128 public static Dictionary < string , List < T > > FindPluginTypes < T > ( string directory ,
171- Func < TypeDefinition , IPluginLoadContext , string , T > typeSelector ,
172- Func < AssemblyDefinition , bool > assemblyFilter = null ,
129+ Func < TypeDefinition , string , T > typeSelector ,
130+ Func < AssemblyDefinition , bool > assemblyFilter =
131+ null ,
173132 string cacheName = null )
174133 where T : ICacheable , new ( )
175134 {
@@ -194,7 +153,19 @@ public static Dictionary<string, List<T>> FindPluginTypes<T>(string directory,
194153 continue ;
195154 }
196155
197- result [ dll ] = ExamineStream ( typeSelector , assemblyFilter , dllMs , null , dll ) ;
156+ using var ass = AssemblyDefinition . ReadAssembly ( dllMs , ReaderParameters ) ;
157+ Logger . Log ( LogLevel . Debug , $ "Examining '{ dll } '") ;
158+
159+ if ( ! assemblyFilter ? . Invoke ( ass ) ?? false )
160+ {
161+ result [ dll ] = new List < T > ( ) ;
162+ continue ;
163+ }
164+
165+ var matches = ass . MainModule . Types
166+ . Select ( t => typeSelector ( t , dll ) )
167+ . Where ( t => t != null ) . ToList ( ) ;
168+ result [ dll ] = matches ;
198169 }
199170 catch ( BadImageFormatException e )
200171 {
@@ -212,82 +183,6 @@ public static Dictionary<string, List<T>> FindPluginTypes<T>(string directory,
212183 return result ;
213184 }
214185
215- /// <summary>
216- /// Looks up assemblies using the given loaders and locates all types that can be loaded and collects their metadata.
217- /// </summary>
218- /// <typeparam name="T">The specific base type to search for.</typeparam>
219- /// <param name="loadContexts">The load contexts to obtain the assemblies from.</param>
220- /// <param name="typeSelector">A function to check if a type should be selected and to build the type metadata.</param>
221- /// <param name="assemblyFilter">A filter function to quickly determine if the assembly can be loaded.</param>
222- /// <param name="cacheName">The name of the cache to get cached types from.</param>
223- /// <returns>
224- /// A dictionary of all assemblies in the directory and the list of type metadatas of types that match the
225- /// selector.
226- /// </returns>
227- public static List < T > GetPluginsFromLoadContexts < T > ( IEnumerable < IPluginLoadContext > loadContexts ,
228- Func < TypeDefinition , IPluginLoadContext , string , T > typeSelector ,
229- Func < AssemblyDefinition , bool > assemblyFilter = null ,
230- string cacheName = null )
231- where T : ICacheable , new ( )
232- {
233- var result = new Dictionary < string , List < T > > ( ) ;
234- var hashes = new Dictionary < string , string > ( ) ;
235- Dictionary < string , CachedAssembly < T > > cache = null ;
236-
237- if ( cacheName != null )
238- cache = LoadAssemblyCache < T > ( cacheName ) ;
239-
240- foreach ( IPluginLoadContext loadContext in loadContexts )
241- {
242- IList < T > plugins ;
243- if ( cache != null && loadContext . AssemblyHash != null &&
244- cache . TryGetValue ( loadContext . AssemblyIdentifier , out var cacheEntry ) &&
245- loadContext . AssemblyHash == cacheEntry . Hash )
246- {
247- plugins = cacheEntry . CacheItems ;
248- }
249- else
250- {
251- var assemblyData = loadContext . GetAssemblyData ( ) ;
252- using var memory = new MemoryStream ( assemblyData ) ;
253- plugins = ExamineStream ( typeSelector , assemblyFilter , memory , loadContext , null ) ;
254- }
255-
256- foreach ( T pluginInfo in plugins )
257- {
258- if ( ! result . ContainsKey ( loadContext . AssemblyIdentifier ) )
259- result [ loadContext . AssemblyIdentifier ] = new ( ) ;
260- result [ loadContext . AssemblyIdentifier ] . Add ( pluginInfo ) ;
261- }
262- }
263-
264- if ( cache != null )
265- SaveAssemblyCache ( cacheName , result , hashes ) ;
266-
267- return result . SelectMany ( x => x . Value ) . ToList ( ) ;
268- }
269-
270- private static List < T > ExamineStream < T > ( Func < TypeDefinition , IPluginLoadContext , string , T > typeSelector ,
271- Func < AssemblyDefinition , bool > assemblyFilter ,
272- MemoryStream dllMs ,
273- IPluginLoadContext loadContext ,
274- string location )
275- where T : ICacheable , new ( )
276- {
277- using var ass = AssemblyDefinition . ReadAssembly ( dllMs , ReaderParameters ) ;
278- Logger . Log ( LogLevel . Debug , $ "Examining '{ ass . Name } '") ;
279-
280- if ( ! assemblyFilter ? . Invoke ( ass ) ?? false )
281- {
282- return new List < T > ( ) ;
283- }
284-
285- var matches = ass . MainModule . Types
286- . Select ( t => typeSelector ( t , loadContext , location ) )
287- . Where ( t => t != null ) . ToList ( ) ;
288- return matches ;
289- }
290-
291186 /// <summary>
292187 /// Loads an index of type metadatas from a cache.
293188 /// </summary>
@@ -310,9 +205,7 @@ public static Dictionary<string, CachedAssembly<T>> LoadAssemblyCache<T>(string
310205 if ( ! File . Exists ( path ) )
311206 return null ;
312207
313- using var br = new BinaryReader ( File . OpenRead ( path ) ) ;
314- var version = br . ReadInt32 ( ) ;
315- if ( version == CachedAssembly < T > . Version )
208+ using ( var br = new BinaryReader ( File . OpenRead ( path ) ) )
316209 {
317210 var entriesCount = br . ReadInt32 ( ) ;
318211
@@ -366,7 +259,6 @@ public static void SaveAssemblyCache<T>(string cacheName,
366259 var path = Path . Combine ( Paths . CachePath , $ "{ cacheName } _typeloader.dat") ;
367260
368261 using var bw = new BinaryWriter ( File . OpenWrite ( path ) ) ;
369- bw . Write ( CachedAssembly < T > . Version ) ;
370262 bw . Write ( entries . Count ) ;
371263
372264 foreach ( var kv in entries )
0 commit comments