@@ -17,8 +17,16 @@ internal class AssemblyManager
17
17
{
18
18
// modified from event handlers below, potentially triggered from different .NET threads
19
19
// therefore this should be a ConcurrentDictionary
20
+ //
21
+ // WARNING: Dangerous if cross-app domain usage is ever supported
22
+ // Reusing the dictionary with assemblies accross multiple initializations is problematic.
23
+ // Loading happens from CurrentDomain (see line 53). And if the first call is from AppDomain that is later unloaded,
24
+ // than it can end up referring to assemblies that are already unloaded (default behavior after unload appDomain -
25
+ // unless LoaderOptimization.MultiDomain is used);
26
+ // So for multidomain support it is better to have the dict. recreated for each app-domain initialization
20
27
private static ConcurrentDictionary < string , ConcurrentDictionary < Assembly , string > > namespaces =
21
28
new ConcurrentDictionary < string , ConcurrentDictionary < Assembly , string > > ( ) ;
29
+
22
30
//private static Dictionary<string, Dictionary<string, string>> generics;
23
31
private static AssemblyLoadEventHandler lhandler ;
24
32
private static ResolveEventHandler rhandler ;
@@ -27,7 +35,7 @@ internal class AssemblyManager
27
35
private static Dictionary < string , int > probed = new Dictionary < string , int > ( 32 ) ;
28
36
29
37
// modified from event handlers below, potentially triggered from different .NET threads
30
- private static AssemblyList assemblies ;
38
+ private static ConcurrentQueue < Assembly > assemblies ;
31
39
internal static List < string > pypath ;
32
40
33
41
private AssemblyManager ( )
@@ -58,7 +66,7 @@ internal static void Initialize()
58
66
try
59
67
{
60
68
ScanAssembly ( a ) ;
61
- assemblies . Add ( a ) ;
69
+ assemblies . Enqueue ( a ) ;
62
70
}
63
71
catch ( Exception ex )
64
72
{
@@ -89,7 +97,7 @@ internal static void Shutdown()
89
97
private static void AssemblyLoadHandler ( object ob , AssemblyLoadEventArgs args )
90
98
{
91
99
Assembly assembly = args . LoadedAssembly ;
92
- assemblies . Add ( assembly ) ;
100
+ assemblies . Enqueue ( assembly ) ;
93
101
ScanAssembly ( assembly ) ;
94
102
}
95
103
@@ -459,103 +467,5 @@ public static Type LookupType(string qname)
459
467
}
460
468
return null ;
461
469
}
462
-
463
- /// <summary>
464
- /// Wrapper around List<Assembly> for thread safe access
465
- /// </summary>
466
- private class AssemblyList : IEnumerable < Assembly >
467
- {
468
- private readonly List < Assembly > _list ;
469
- private readonly ReaderWriterLockSlim _lock ;
470
-
471
- public AssemblyList ( int capacity )
472
- {
473
- _list = new List < Assembly > ( capacity ) ;
474
- _lock = new ReaderWriterLockSlim ( ) ;
475
- }
476
-
477
- public int Count
478
- {
479
- get
480
- {
481
- _lock . EnterReadLock ( ) ;
482
- try
483
- {
484
- return _list . Count ;
485
- }
486
- finally
487
- {
488
- _lock . ExitReadLock ( ) ;
489
- }
490
- }
491
- }
492
-
493
- public void Add ( Assembly assembly )
494
- {
495
- _lock . EnterWriteLock ( ) ;
496
- try
497
- {
498
- _list . Add ( assembly ) ;
499
- }
500
- finally
501
- {
502
- _lock . ExitWriteLock ( ) ;
503
- }
504
- }
505
-
506
- public IEnumerator GetEnumerator ( )
507
- {
508
- return ( ( IEnumerable < Assembly > ) this ) . GetEnumerator ( ) ;
509
- }
510
-
511
- /// <summary>
512
- /// Enumerator wrapping around <see cref="AssemblyList._list" />'s enumerator.
513
- /// Acquires and releases a read lock on <see cref="AssemblyList._lock" /> during enumeration
514
- /// </summary>
515
- private class Enumerator : IEnumerator < Assembly >
516
- {
517
- private readonly AssemblyList _assemblyList ;
518
-
519
- private readonly IEnumerator < Assembly > _listEnumerator ;
520
-
521
- public Enumerator ( AssemblyList assemblyList )
522
- {
523
- _assemblyList = assemblyList ;
524
- _assemblyList . _lock . EnterReadLock ( ) ;
525
- _listEnumerator = _assemblyList . _list . GetEnumerator ( ) ;
526
- }
527
-
528
- public void Dispose ( )
529
- {
530
- _listEnumerator . Dispose ( ) ;
531
- _assemblyList . _lock . ExitReadLock ( ) ;
532
- }
533
-
534
- public bool MoveNext ( )
535
- {
536
- return _listEnumerator . MoveNext ( ) ;
537
- }
538
-
539
- public void Reset ( )
540
- {
541
- _listEnumerator . Reset ( ) ;
542
- }
543
-
544
- public Assembly Current
545
- {
546
- get { return _listEnumerator . Current ; }
547
- }
548
-
549
- object IEnumerator . Current
550
- {
551
- get { return Current ; }
552
- }
553
- }
554
-
555
- IEnumerator < Assembly > IEnumerable < Assembly > . GetEnumerator ( )
556
- {
557
- return new Enumerator ( this ) ;
558
- }
559
- }
560
470
}
561
471
}
0 commit comments