예제 #1
0
            private void SubChannelStarted(int id, SubChannel channel)
            {
                var res = _subChannels.GetOrAdd(id, channel);

                Contracts.Assert(res == channel);
            }
예제 #2
0
        /// <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
                }
            }
        }