private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args) { var assembly = args.LoadedAssembly; if (ShouldIgnoreAssembly(assembly)) { return; } if (Monitor.TryEnter(_lockObject)) { var assemblyName = assembly.FullName; if (!_loadedAssemblies.Contains(assemblyName)) { if (_isLoading) { _assemblyLoadDelayQueue.Enqueue(assembly); } else { try { _isLoading = true; InitializeTypes(assembly); } finally { while (_assemblyLoadDelayQueue.Count > 0) { var delayedAssembly = _assemblyLoadDelayQueue.Dequeue(); InitializeTypes(delayedAssembly); } _isLoading = false; } } } var types = GetTypesOfAssembly(assembly); Monitor.Exit(_lockObject); var handler = AssemblyLoaded; if (!(handler is null)) { var eventArgs = new AssemblyLoadedEventArgs(assembly, types); handler(null, eventArgs); } } else { lock (_assemblyQueue) { _assemblyQueue.Enqueue(assembly); } } }
private static void InitializeAssemblies(IEnumerable <Assembly> assemblies, bool force, bool allowMultithreadedInitialization = false) { // Important note: only allow explicit multithreaded initialization var listForLoadedEvent = new List <Tuple <Assembly, Type[]> >(); lock (_lockObject) { var assembliesToRetrieve = new List <Assembly>(); foreach (var assembly in assemblies) { var loadedAssemblyFullName = assembly.FullName; var containsLoadedAssembly = _loadedAssemblies.Contains(loadedAssemblyFullName); if (!force && containsLoadedAssembly) { continue; } if (!containsLoadedAssembly) { _loadedAssemblies.Add(loadedAssemblyFullName); } if (ShouldIgnoreAssembly(assembly)) { continue; } assembliesToRetrieve.Add(assembly); } var typesToAdd = GetAssemblyTypes(assembliesToRetrieve, allowMultithreadedInitialization); foreach (var assemblyWithTypes in typesToAdd) { foreach (var type in assemblyWithTypes.Value) { InitializeType(assemblyWithTypes.Key, type); } } var lateLoadedAssemblies = new List <Assembly>(); lock (_assemblyQueue) { while (_assemblyQueue.Count > 0) { var assembly = _assemblyQueue.Dequeue(); lateLoadedAssemblies.Add(assembly); } } foreach (var lateLoadedAssembly in lateLoadedAssemblies) { var tuple = Tuple.Create(lateLoadedAssembly, GetTypesOfAssembly(lateLoadedAssembly)); listForLoadedEvent.Add(tuple); } } // Calling out of lock statement, but still may happens that would be called inside of it var handler = AssemblyLoaded; if (handler != null) { foreach (var tuple in listForLoadedEvent) { var assembly = tuple.Item1; var types = tuple.Item2; var eventArgs = new AssemblyLoadedEventArgs(assembly, types); handler(null, eventArgs); } } }