private void ProcessExtensionReference(ExtensionLoadingContext context,
                                               string referenceName,
                                               IList <DependencyReferenceDescriptor> activatedReferences)
        {
            // If the reference is an extension has been processed already, use the same loader as
            // that extension, since a given extension should be loaded with a unique loader for the
            // whole application
            var bestExtensionReference = context.ProcessedExtensions.ContainsKey(referenceName) ?
                                         context.ProcessedExtensions[referenceName] :
                                         null;

            // Activated the extension reference
            if (bestExtensionReference != null)
            {
                activatedReferences.Add(new DependencyReferenceDescriptor
                {
                    LoaderName  = bestExtensionReference.Loader.Name,
                    Name        = referenceName,
                    VirtualPath = bestExtensionReference.VirtualPath
                });

                return;
            }

            // Skip references from "~/bin"
            if (buildManager.HasReferencedAssembly(referenceName))
            {
                return;
            }

            // Binary references
            var references = context.ReferencesByName.ContainsKey(referenceName) ?
                             context.ReferencesByName[referenceName] :
                             Enumerable.Empty <ExtensionReferenceProbeEntry>();

            var bestBinaryReference = references
                                      .Where(entry => !string.IsNullOrEmpty(entry.VirtualPath))
                                      .Select(entry => new { Entry = entry, LastWriteTimeUtc = virtualPathProvider.GetFileLastWriteTimeUtc(entry.VirtualPath) })
                                      .OrderBy(e => e.LastWriteTimeUtc)
                                      .ThenBy(e => e.Entry.Name)
                                      .FirstOrDefault();

            // Activate the binary ref
            if (bestBinaryReference != null)
            {
                if (!context.ProcessedReferences.ContainsKey(bestBinaryReference.Entry.Name))
                {
                    context.ProcessedReferences.Add(bestBinaryReference.Entry.Name, bestBinaryReference.Entry);
                    bestBinaryReference.Entry.Loader.ReferenceActivated(context, bestBinaryReference.Entry);
                }
                activatedReferences.Add(new DependencyReferenceDescriptor
                {
                    LoaderName  = bestBinaryReference.Entry.Loader.Name,
                    Name        = bestBinaryReference.Entry.Name,
                    VirtualPath = bestBinaryReference.Entry.VirtualPath
                });
            }
        }
        private void ProcessContextCommands(ExtensionLoadingContext ctx)
        {
            Logger.Info("Executing list of operations needed for loading extensions...");
            foreach (var action in ctx.DeleteActions)
            {
                action();
            }

            foreach (var action in ctx.CopyActions)
            {
                action();
            }
        }
        private string GetExtensionHash(ExtensionLoadingContext context, DependencyDescriptor dependencyDescriptor)
        {
            var hash = new Hash();

            hash.AddStringInvariant(dependencyDescriptor.Name);

            foreach (var virtualpathDependency in context.ProcessedExtensions[dependencyDescriptor.Name].VirtualPathDependencies)
            {
                hash.AddDateTime(GetVirtualPathModificationTimeUtc(context.VirtualPathModficationDates, virtualpathDependency));
            }

            foreach (var reference in dependencyDescriptor.References)
            {
                hash.AddStringInvariant(reference.Name);
                hash.AddString(reference.LoaderName);
                hash.AddDateTime(GetVirtualPathModificationTimeUtc(context.VirtualPathModficationDates, reference.VirtualPath));
            }

            return(hash.Value);
        }
        private IEnumerable <DependencyReferenceDescriptor> ProcessExtensionReferences(ExtensionLoadingContext context, ExtensionProbeEntry activatedExtension)
        {
            if (activatedExtension == null)
            {
                return(Enumerable.Empty <DependencyReferenceDescriptor>());
            }

            var referenceNames = (context.ReferencesByModule.ContainsKey(activatedExtension.Descriptor.Id) ?
                                  context.ReferencesByModule[activatedExtension.Descriptor.Id] :
                                  Enumerable.Empty <ExtensionReferenceProbeEntry>())
                                 .Select(r => r.Name)
                                 .Distinct(StringComparer.OrdinalIgnoreCase);

            var referencesDecriptors = new List <DependencyReferenceDescriptor>();

            foreach (var referenceName in referenceNames)
            {
                ProcessExtensionReference(context, referenceName, referencesDecriptors);
            }

            return(referencesDecriptors);
        }
        private void ProcessExtension(ExtensionLoadingContext context, ExtensionDescriptor extension)
        {
            var extensionProbes = context.AvailableExtensionsProbes.ContainsKey(extension.Id) ?
                                  context.AvailableExtensionsProbes[extension.Id] :
                                  Enumerable.Empty <ExtensionProbeEntry>();

            // materializes the list
            extensionProbes = extensionProbes.ToArray();

            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat("Loaders for extension \"{0}\": ", extension.Id);
                foreach (var probe in extensionProbes)
                {
                    Logger.DebugFormat("  Loader: {0}", probe.Loader.Name);
                    Logger.DebugFormat("    VirtualPath: {0}", probe.VirtualPath);
                    Logger.DebugFormat("    VirtualPathDependencies: {0}", string.Join(", ", probe.VirtualPathDependencies));
                }
            }

            var moduleReferences =
                context.AvailableExtensions
                .Where(e =>
                       context.ReferencesByModule.ContainsKey(extension.Id) &&
                       context.ReferencesByModule[extension.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(e.Id, r.Name)))
                .ToList();

            var processedModuleReferences =
                moduleReferences
                .Where(e => context.ProcessedExtensions.ContainsKey(e.Id))
                .Select(e => context.ProcessedExtensions[e.Id])
                .ToList();

            var activatedExtension = extensionProbes.FirstOrDefault(
                e => e.Loader.IsCompatibleWithModuleReferences(extension, processedModuleReferences)
                );

            var previousDependency = context.PreviousDependencies.FirstOrDefault(
                d => StringComparer.OrdinalIgnoreCase.Equals(d.Name, extension.Id)
                );

            if (activatedExtension == null)
            {
                Logger.WarnFormat("No loader found for extension \"{0}\"!", extension.Id);
            }

            var references = ProcessExtensionReferences(context, activatedExtension);

            foreach (var loader in loaders)
            {
                if (activatedExtension != null && activatedExtension.Loader.Name == loader.Name)
                {
                    Logger.InfoFormat("Activating extension \"{0}\" with loader \"{1}\"", activatedExtension.Descriptor.Id, loader.Name);
                    loader.ExtensionActivated(context, extension);
                }
                else if (previousDependency != null && previousDependency.LoaderName == loader.Name)
                {
                    Logger.InfoFormat("Deactivating extension \"{0}\" from loader \"{1}\"", previousDependency.Name, loader.Name);
                    loader.ExtensionDeactivated(context, extension);
                }
            }

            if (activatedExtension != null)
            {
                context.NewDependencies.Add(new DependencyDescriptor
                {
                    Name        = extension.Id,
                    LoaderName  = activatedExtension.Loader.Name,
                    VirtualPath = activatedExtension.VirtualPath,
                    References  = references
                });
            }

            // Keep track of which loader we use for every extension
            // This will be needed for processing references from other dependent extensions
            context.ProcessedExtensions.Add(extension.Id, activatedExtension);
        }