private void SubChannelStarted(int id, SubChannel channel) { var res = _subChannels.GetOrAdd(id, channel); Contracts.Assert(res == channel); }
/// <summary> /// This loads assemblies that are in our "root" directory (where this assembly is) and caches /// information for the loadable classes in loaded assemblies. /// </summary> private static void CacheLoadedAssemblies() { // The target assembly is the one containing LoadableClassAttributeBase. If an assembly doesn't reference // the target, then we don't want to scan its assembly attributes (there's no point in doing so). var target = typeof(LoadableClassAttributeBase).Assembly; lock (_lock) { if (_assemblyQueue == null) { // Create the loaded assembly queue and dictionary, set up the AssemblyLoad / AssemblyResolve // event handlers and populate the queue / dictionary with all assemblies that are currently loaded. Contracts.Assert(_assemblyQueue == null); Contracts.Assert(_loadedAssemblies == null); _assemblyQueue = new ConcurrentQueue <Assembly>(); _loadedAssemblies = new ConcurrentDictionary <string, Assembly>(); AppDomain.CurrentDomain.AssemblyLoad += CurrentDomainAssemblyLoad; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve; foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { // Ignore dynamic assemblies. if (a.IsDynamic) { continue; } _assemblyQueue.Enqueue(a); if (!_loadedAssemblies.TryAdd(a.FullName, a)) { // Duplicate loading. Console.Error.WriteLine("Duplicate loaded assembly '{0}'", a.FullName); } } // Load all assemblies in our directory. var moduleName = typeof(ComponentCatalog).Module.FullyQualifiedName; // If were are loaded in the context of SQL CLR then the FullyQualifiedName and Name properties are set to // string "<Unknown>" and we skip scanning current directory. if (moduleName != "<Unknown>") { string dir = Path.GetDirectoryName(moduleName); LoadAssembliesInDir(dir, true); dir = Path.Combine(dir, "AutoLoad"); LoadAssembliesInDir(dir, true); } } Contracts.AssertValue(_assemblyQueue); Contracts.AssertValue(_loadedAssemblies); Assembly assembly; while (_assemblyQueue.TryDequeue(out assembly)) { if (!_cachedAssemblies.Add(assembly.FullName)) { continue; } if (assembly != target) { bool found = false; var targetName = target.GetName(); foreach (var name in assembly.GetReferencedAssemblies()) { if (name.Name == targetName.Name) { found = true; break; } } if (!found) { continue; } } #if TRACE_ASSEMBLY_LOADING // The "" no-op argument is necessary because WriteLine has multiple overloads, and with two strings // it will be the one that is message/category, rather than format string with System.Diagnostics.Debug.WriteLine("*** Caching classes in {0}", assembly.FullName, ""); #endif int added = 0; foreach (LoadableClassAttributeBase attr in assembly.GetCustomAttributes(typeof(LoadableClassAttributeBase))) { MethodInfo getter = null; ConstructorInfo ctor = null; MethodInfo create = null; bool requireEnvironment = false; if (attr.InstanceType != typeof(void) && !TryGetIniters(attr.InstanceType, attr.LoaderType, attr.CtorTypes, out getter, out ctor, out create, out requireEnvironment)) { Console.Error.WriteLine( "CacheClassesFromAssembly: can't instantiate loadable class {0} with name {1}", attr.InstanceType.Name, attr.LoadNames[0]); Contracts.Assert(getter == null && ctor == null && create == null); } var info = new LoadableClassInfo(attr, getter, ctor, create, requireEnvironment); AddClass(info, attr.LoadNames); added++; } #if TRACE_ASSEMBLY_LOADING System.Diagnostics.Debug.WriteLine(" Found {0} entries in {1}", added, assembly.FullName); #endif } } }