コード例 #1
0
        private static IContainer ScanGacForAutofacModulesAndCreateContainer(string appRootNamespace, Func<string, bool> assemblyFileNameMatchingPredicate)
        {
            using (new SPMonitoredScope("Dynamite - Bootstrapping dependency injection container " + appRootNamespace + " and scanning GAC for Modules."))
            {
                var containerBuilderForDynamiteComponents = new ContainerBuilder();
                var assemblyLocator = new GacAssemblyLocator();

                // Don't just scan the GAC modules, also prepare the Dynamite core utils (by passing the params in ourselves).
                // I.E. each container gets its own DynamiteRegistrationModule components.
                var dynamiteModule = new AutofacDynamiteRegistrationModule(appRootNamespace);
                containerBuilderForDynamiteComponents.RegisterModule(dynamiteModule);

                var matchingAssemblies = assemblyLocator.GetAssemblies(new List<string> { AssemblyFolder }, assemblyFileNameMatchingPredicate);

                // Make sure we exclude all other GSoft.Dynamite DLLs (i.e. ignore other versions deployed to same GAC)
                // so that other AutofacDynamiteRegistrationModule instances don't get registered.
                var filteredMatchingAssemblies = matchingAssemblies.Where(x => !x.FullName.Contains("GSoft.Dynamite,"));

                // Now make sure all Dynamite component modules (i.e. all DLLs that start with GSoft.Dynamite.*) are registered BEFORE
                // any other modules.
                // This ensures that "client" modules will be able to override the Container registrations of GSoft.Dynamite.Components modules.
                var dynamiteComponentModuleAssemblies = filteredMatchingAssemblies.Where(assembly => assembly.FullName.StartsWith("GSoft.Dynamite."));
                var allTheRest = filteredMatchingAssemblies.Where(assembly => !assembly.FullName.StartsWith("GSoft.Dynamite."));

                // 1) Build the base container with only Dynamite-related components
                AutofacBackportScanningUtils.RegisterAssemblyModules(containerBuilderForDynamiteComponents, dynamiteComponentModuleAssemblies.ToArray());
                var container = containerBuilderForDynamiteComponents.Build();

                var logger = container.Resolve<ILogger>();
                string dynamiteAssemblyNameEnumeration = string.Empty;
                dynamiteComponentModuleAssemblies.Cast<Assembly>().ToList().ForEach(a => dynamiteAssemblyNameEnumeration += a.FullName + ", ");
                logger.Info("Dependency injection module registration for container " + appRootNamespace + ". The following Dynamite component assemblies were scanned and any Autofac Module within was registered. The order of registrations was: " + dynamiteAssemblyNameEnumeration);

                // 2) Extend the original registrations with any remaining AddOns' registrations
                var containerBuilderForAddOns = new ContainerBuilder();
                AutofacBackportScanningUtils.RegisterAssemblyModules(containerBuilderForAddOns, allTheRest.ToArray());
                containerBuilderForAddOns.Update(container);

                string addOnAssemblyNameEnumeration = string.Empty;
                allTheRest.Cast<Assembly>().ToList().ForEach(a => addOnAssemblyNameEnumeration += a.FullName + ", ");
                logger.Info("Dependency injection module registration for container " + appRootNamespace + ". The following Add-On component assemblies (i.e. extensions to the core Dynamite components) were scanned and any Autofac Module within was registered. The order of registrations was: " + addOnAssemblyNameEnumeration);

                // Log the full component registry for easy debugging through ULS
                string componentRegistryAsString = string.Empty;
                var regAndServices = container.ComponentRegistry.Registrations.SelectMany(r => r.Services.OfType<IServiceWithType>(), (r, s) => new { r, s });
                regAndServices.ToList().ForEach(regAndService => componentRegistryAsString += "[" + regAndService.s.ServiceType.FullName + "->" + regAndService.r.Activator.LimitType.FullName + "], ");
                logger.Info("Autofac component registry details for container " + appRootNamespace + ": " + componentRegistryAsString);

                return container;
            }
        }
コード例 #2
0
        private static IContainer ScanGacForAutofacModulesAndCreateContainer(string appRootNamespace, Func<string, bool> assemblyFileNameMatchingPredicate)
        {
            using (new SPMonitoredScope("Dynamite - Bootstrapping dependency injection container " + appRootNamespace + " and scanning GAC for Modules."))
            {
                var containerBuilder = new ContainerBuilder();
                var assemblyLocator = new GacAssemblyLocator();

                // Don't just scan the GAC modules, also prepare the Dynamite core utils (by passing the params in ourselves).
                // I.E. each container gets its own DynamiteRegistrationModule components.
                var dynamiteModule = new AutofacDynamiteRegistrationModule(appRootNamespace);
                containerBuilder.RegisterModule(dynamiteModule);

                var matchingAssemblies = assemblyLocator.GetAssemblies(new List<string> { AssemblyFolder }, assemblyFileNameMatchingPredicate);

                // Make sure we exclude all other GSoft.Dynamite DLLs (i.e. ignore other versions deployed to same GAC)
                // so that other AutofacDynamiteRegistrationModule instances don't get registered.
                var filteredMatchingAssemblies = matchingAssemblies.Where(x => !x.FullName.Contains("GSoft.Dynamite,"));

                AutofacBackportScanningUtils.RegisterAssemblyModules(containerBuilder, filteredMatchingAssemblies.ToArray());

                return containerBuilder.Build();
            }
        }
コード例 #3
0
        private void EnsureServiceLocatorAccessorForCurrentSiteContext(SPSite site)
        {
            if (locatorAccessor == null)
            {
                lock (lockObject)
                {
                    if (this.locatorAccessor == null)
                    {
                        // 1) Scan the GAC for any DLL matching the *.ServiceLocator.DLL pattern
                        var assemblyScanner = new GacAssemblyLocator();
                        var matchingAssemblies = assemblyScanner.GetAssemblies(new List<string>() { "GAC_MSIL" }, assemblyFileName => assemblyFileName.Contains(".ServiceLocator"));

                        Type accessorType = null;

                        if (matchingAssemblies.Any())
                        {
                            var serviceLocatorAssembly = matchingAssemblies[0];

                            if (matchingAssemblies.Count > 1)
                            {
                                // 2) If more than one service locator is found, gotta use the contextual SPSite object
                                //    and extract the preferred service locator setting from its property bag.
                                if (site != null)
                                {
                                    using (var rootWeb = site.OpenWeb())
                                    {
                                        string serviceLocatorAssemlyName = rootWeb.Properties[KeyServiceLocatorAssemblyName];

                                        serviceLocatorAssembly = matchingAssemblies.FirstOrDefault(assembly => assembly.FullName.Contains(serviceLocatorAssemlyName));
                                    }
                                }
                                else
                                {
                                    throw new ArgumentNullException("site");
                                }
                            }

                            if (serviceLocatorAssembly != null)
                            {
                                // Only one matching assembly, find its accessor class
                                accessorType = this.FindServiceLocatorAccessorType(serviceLocatorAssembly);
                            }
                            else
                            {
                                throw new InvalidOperationException("Failed to find an assembly matching the *.ServiceLocator.DLL pattern to provide a service locator.");
                            }
                        }

                        if (accessorType != null)
                        {
                            // 3) Create the accessor instance
                            this.locatorAccessor = (ISharePointServiceLocatorAccessor)Activator.CreateInstance(accessorType);
                        }
                        else
                        {
                            throw new InvalidOperationException("Failed to find implementation of ISharePointServiceLocatorAccessor for AddOnProvidedServiceLocator. Your *.ServiceLocator.DLL assembly should expose its static container through that interface.");
                        }

                    }
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Triggers ServiceLocator bootstrapping (scans the GAC for assemblies with a name
        /// that matches *.ServiceLocator.DLL, by convention).
        /// </summary>
        /// <param name="web">The context's SPWeb. Keep null if none available.</param>
        /// <param name="site">The context's SPSite. Keep null if none available.</param>
        /// <param name="webApplication">The context's SPWebApplication. Keep null if none available.</param>
        /// <param name="farm">The context's SPFarm. Keep null if none available.</param>
        private void EnsureServiceLocatorAccessor(SPWeb web, SPSite site, SPWebApplication webApplication, SPFarm farm)
        {
            if (locatorAccessor == null)
            {
                lock (lockObject)
                {
                    if (this.locatorAccessor == null)
                    {
                        try
                        {
                            // 1) Scan the GAC for any DLL matching the *.ServiceLocator.DLL pattern
                            var assemblyScanner = new GacAssemblyLocator();
                            var matchingAssemblies = assemblyScanner.GetAssemblies(new List<string>() { "GAC_MSIL" }, assemblyFileName => assemblyFileName.Contains(".ServiceLocator"));

                            Assembly serviceLocatorAssembly = null;
                            Type accessorType = null;

                            if (matchingAssemblies.Any())
                            {

                                if (matchingAssemblies.Count > 1)
                                {
                                    // 2) If more than one service locator is found, we must disambiguate. We have to use the
                                    //    contextual SPWeb, SPSite, SPWebApp or SPFarm objects and extract the preferred service
                                    //    locator assembly name setting from their property bag.
                                    //    The SPWeb's property bag is inspected first, if available, then the SPSite's RootWeb property
                                    //    bag, then the SPWebApp's, then the SPFarm's property bag as a last resort.
                                    string contextObjectWhereDiscriminatorWasFound;
                                    string serviceLocatorAssemblyNameDiscriminator = this.FindServiceLocatorAccessorTypeNameFromMostSpecificPropertyBag(web, site, webApplication, farm, out contextObjectWhereDiscriminatorWasFound);

                                    string allServiceLocatorAssemblyNames = string.Join(";", matchingAssemblies.Select(locatorAssembly => locatorAssembly.FullName).ToArray());
                                    string basicDisambiguationErrorMessage = string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Failed to disambiguate between all DLLs in the GAC that match the *.ServiceLocator.DLL filename pattern. All matching assemblies in GAC: {0}.",
                                        allServiceLocatorAssemblyNames);

                                    if (!string.IsNullOrEmpty(serviceLocatorAssemblyNameDiscriminator))
                                    {
                                        // We found a ServiceLocator assembly name in one of the context's Property Bags.
                                        serviceLocatorAssembly = matchingAssemblies.FirstOrDefault(assembly => assembly.FullName.Contains(serviceLocatorAssemblyNameDiscriminator));

                                        if (serviceLocatorAssembly == null)
                                        {
                                            throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                                " The discriminator found in one of the context's Property Bags (value=" + serviceLocatorAssemblyNameDiscriminator +
                                                ", property bag location=" + contextObjectWhereDiscriminatorWasFound + ") did not match either of the " +
                                                matchingAssemblies.Count + " ServiceLocator DLLs available in GAC. The discriminator value should match one of the DLLs so that we can determine which to use.");
                                        }
                                    }
                                    else
                                    {
                                        // We failed to find a disambiguator setting in all of the context's Property Bags
                                        throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                            " You cannot begin injection from the root application container if more that one ServiceLocator assembly exists in the GAC." +
                                            " You must begin injection with one of the following methods on your ISharePointServiceLocator: BeginLifetimeScope(SPFeature) or" +
                                            " BeginLifetimeScope(SPWeb) or BeginLifetimeScope(SPSite) or BeginLifetimeScope(SPWebApplication) or BeginLifetimeScope(SPFarm)," +
                                            " depending on your context. IMPORTANT: The property bags on the context' SPWeb, SPSite, SPWebApplication and SPFarm will be inspected" +
                                            " (in that order) to find a value for the key '" + KeyServiceLocatorAssemblyName + "'. This discriminator value will indicate to Dynamite's" +
                                            " AddOnProvidedServiceLocator which concrete add-on's ServiceLocator DLL to use in the current context.");
                                    }
                                }
                                else
                                {
                                    // Only one ServiceLocator DLL found in GAC. There is no ambiguity: use this locator.
                                    serviceLocatorAssembly = matchingAssemblies[0];
                                }

                                if (serviceLocatorAssembly != null)
                                {
                                    // At this point we figured out the right matching assembly: find its accessor class within its types
                                    accessorType = this.FindServiceLocatorAccessorType(serviceLocatorAssembly);
                                }
                            }
                            else
                            {
                                // Not even one DLL in GAC matches the *.ServiceLocator.DLL pattern
                                throw new InvalidOperationException("Failed to find any assembly in the GAC that matches the *.ServiceLocator.DLL pattern.");
                            }

                            if (accessorType != null)
                            {
                                // 3) Create the accessor instance
                                this.locatorAccessor = (ISharePointServiceLocatorAccessor)Activator.CreateInstance(accessorType);
                            }
                            else
                            {
                                throw new InvalidOperationException("Failed to find implementation of ISharePointServiceLocatorAccessor for AddOnProvidedServiceLocator. Your ServiceLocator assembly (" + serviceLocatorAssembly.FullName + ") should expose its static container through that interface.");
                            }
                        }
                        catch (InvalidOperationException exception)
                        {
                            var logger = new TraceLogger("GSoft.Dynamite", "GSoft.Dynamite", false);
                            logger.Error(
                                "AddOnProvidedServiceLocator Initialization Error - An error occured while trying to find a DLL matching the pattern *ServiceLocator.dll in the GAC. The FallbackServiceLocator will be used instead as a last resort (no AddOn registration module will be registered). Exception: {0}",
                                exception.ToString());

                            // Either no assembly in the GAC matches the pattern *.ServiceLocator.DLL pattern,
                            // or in the matching assembly that was found, no class implements ISharePointServiceLocatorAccessor.
                            // In this case, use our default all-available-Dynamite-modules-only service locator
                            this.locatorAccessor = new FallbackServiceLocator();
                        }

                    }
                }
            }
        }