/V2.2/trunk/CAL/Desktop/Composite/Modularity/ModuleManager.cs
C# | 253 lines | 171 code | 32 blank | 50 comment | 37 complexity | c5c05c4d0c3effb23b914afe3225958b MD5 | raw file
- //===================================================================================
- // Microsoft patterns & practices
- // Composite Application Guidance for Windows Presentation Foundation and Silverlight
- //===================================================================================
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
- // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
- // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- // FITNESS FOR A PARTICULAR PURPOSE.
- //===================================================================================
- // The example companies, organizations, products, domain names,
- // e-mail addresses, logos, people, places, and events depicted
- // herein are fictitious. No association with any real company,
- // organization, product, domain name, email address, logo, person,
- // places, or events is intended or should be inferred.
- //===================================================================================
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using Microsoft.Practices.Composite.Logging;
- using Microsoft.Practices.Composite.Properties;
-
- namespace Microsoft.Practices.Composite.Modularity
- {
- /// <summary>
- /// Component responsible for coordinating the modules' type loading and module initialization process.
- /// </summary>
- public partial class ModuleManager : IModuleManager
- {
- private readonly IModuleInitializer moduleInitializer;
- private readonly IModuleCatalog moduleCatalog;
- private readonly ILoggerFacade loggerFacade;
- private IEnumerable<IModuleTypeLoader> typeLoaders;
-
- /// <summary>
- /// Initializes an instance of the <see cref="ModuleManager"/> class.
- /// </summary>
- /// <param name="moduleInitializer">Service used for initialization of modules.</param>
- /// <param name="moduleCatalog">Catalog that enumerates the modules to be loaded and initialized.</param>
- /// <param name="loggerFacade">Logger used during the load and initialization of modules.</param>
- public ModuleManager(IModuleInitializer moduleInitializer, IModuleCatalog moduleCatalog, ILoggerFacade loggerFacade)
- {
- if (moduleInitializer == null)
- {
- throw new ArgumentNullException("moduleInitializer");
- }
-
- if (moduleCatalog == null)
- {
- throw new ArgumentNullException("moduleCatalog");
- }
-
- if (loggerFacade == null)
- {
- throw new ArgumentNullException("loggerFacade");
- }
-
- this.moduleInitializer = moduleInitializer;
- this.moduleCatalog = moduleCatalog;
- this.loggerFacade = loggerFacade;
- }
-
- /// <summary>
- /// Initializes the modules marked as <see cref="InitializationMode.WhenAvailable"/> on the <see cref="ModuleCatalog"/>.
- /// </summary>
- public void Run()
- {
- this.moduleCatalog.Initialize();
-
- this.LoadModulesWhenAvailable();
- }
-
- /// <summary>
- /// Initializes the module on the <see cref="ModuleCatalog"/> with the name <paramref name="moduleName"/>.
- /// </summary>
- /// <param name="moduleName">Name of the module requested for initialization.</param>
- public void LoadModule(string moduleName)
- {
- IEnumerable<ModuleInfo> module = this.moduleCatalog.Modules.Where(m => m.ModuleName == moduleName);
- if (module == null || module.Count() != 1)
- {
- throw new ModuleNotFoundException(moduleName, string.Format(CultureInfo.CurrentCulture, Resources.ModuleNotFound, moduleName));
- }
-
- IEnumerable<ModuleInfo> modulesToLoad = this.moduleCatalog.CompleteListWithDependencies(module);
-
- this.LoadModuleTypes(modulesToLoad);
- }
-
- /// <summary>
- /// Checks if the module needs to be retrieved before it's initialized.
- /// </summary>
- /// <param name="moduleInfo">Module that is being checked if needs retrieval.</param>
- /// <returns></returns>
- protected virtual bool ModuleNeedsRetrieval(ModuleInfo moduleInfo)
- {
- if (moduleInfo.State == ModuleState.NotStarted)
- {
- // If we can instantiate the type, that means the module's assembly is already loaded into
- // the AppDomain and we don't need to retrieve it.
- bool isAvailable = Type.GetType(moduleInfo.ModuleType) != null;
- if (isAvailable)
- {
- moduleInfo.State = ModuleState.ReadyForInitialization;
- }
-
- return !isAvailable;
- }
-
- return false;
- }
-
- /// <summary>
- /// Handles any exception ocurred in the module typeloading process,
- /// logs the error using the <seealso cref="ILoggerFacade"/> and throws a <seealso cref="ModuleTypeLoadingException"/>.
- /// This method can be overriden to provide a different behavior.
- /// </summary>
- /// <param name="moduleInfo">The module metadata where the error happenened.</param>
- /// <param name="exception">The exception thrown that is the cause of the current error.</param>
- /// <exception cref="ModuleTypeLoadingException"></exception>
- protected virtual void HandleModuleTypeLoadingError(ModuleInfo moduleInfo, Exception exception)
- {
- ModuleTypeLoadingException moduleTypeLoadingException = exception as ModuleTypeLoadingException;
-
- if (moduleTypeLoadingException == null)
- {
- moduleTypeLoadingException = new ModuleTypeLoadingException(moduleInfo.ModuleName, exception.Message, exception);
- }
-
- this.loggerFacade.Log(moduleTypeLoadingException.Message, Category.Exception, Priority.High);
-
- throw moduleTypeLoadingException;
- }
-
- private void LoadModulesWhenAvailable()
- {
- IEnumerable<ModuleInfo> whenAvailableModules = this.moduleCatalog.Modules.Where(m => m.InitializationMode == InitializationMode.WhenAvailable);
- IEnumerable<ModuleInfo> modulesToLoadTypes = this.moduleCatalog.CompleteListWithDependencies(whenAvailableModules);
- if (modulesToLoadTypes != null)
- {
- this.LoadModuleTypes(modulesToLoadTypes);
- }
- }
-
- private void LoadModuleTypes(IEnumerable<ModuleInfo> moduleInfos)
- {
- if (moduleInfos == null)
- {
- return;
- }
-
- foreach (ModuleInfo moduleInfo in moduleInfos)
- {
- if (moduleInfo.State == ModuleState.NotStarted)
- {
- if (this.ModuleNeedsRetrieval(moduleInfo))
- {
- this.BeginRetrievingModule(moduleInfo);
- }
- else
- {
- moduleInfo.State = ModuleState.ReadyForInitialization;
- }
- }
- }
-
- this.LoadModulesThatAreReadyForLoad();
- }
-
- private void BeginRetrievingModule(ModuleInfo moduleInfo)
- {
- ModuleInfo moduleInfoToLoadType = moduleInfo;
- IModuleTypeLoader moduleTypeLoader = this.GetTypeLoaderForModule(moduleInfoToLoadType);
- moduleInfoToLoadType.State = ModuleState.LoadingTypes;
- moduleTypeLoader.BeginLoadModuleType(moduleInfo, this.OnModuleTypeLoaded);
- }
-
- private void OnModuleTypeLoaded(ModuleInfo typeLoadedModuleInfo, Exception error)
- {
- if (error == null)
- {
- typeLoadedModuleInfo.State = ModuleState.ReadyForInitialization;
-
- // This callback may call back on the UI thread, but we are not guaranteeing it.
- // If you were to add a custom retriever that retrieved in the background, you
- // would need to consider dispatching to the UI thread.
- this.LoadModulesThatAreReadyForLoad();
- }
- else
- {
- this.HandleModuleTypeLoadingError(typeLoadedModuleInfo, error);
- }
- }
-
- private void LoadModulesThatAreReadyForLoad()
- {
- bool keepLoading = true;
- while (keepLoading)
- {
- keepLoading = false;
- IEnumerable<ModuleInfo> availableModules = this.moduleCatalog.Modules.Where(m => m.State == ModuleState.ReadyForInitialization);
-
- foreach (ModuleInfo moduleInfo in availableModules)
- {
- if (this.AreDependenciesLoaded(moduleInfo))
- {
- moduleInfo.State = ModuleState.Initializing;
- this.InitializeModule(moduleInfo);
- keepLoading = true;
- break;
- }
- }
- }
- }
-
- private bool AreDependenciesLoaded(ModuleInfo moduleInfo)
- {
- IEnumerable<ModuleInfo> requiredModules = this.moduleCatalog.GetDependentModules(moduleInfo);
- if (requiredModules == null)
- {
- return true;
- }
-
- int notReadyRequiredModuleCount =
- requiredModules.Count(requiredModule => requiredModule.State != ModuleState.Initialized);
-
- return notReadyRequiredModuleCount == 0;
- }
-
- private IModuleTypeLoader GetTypeLoaderForModule(ModuleInfo moduleInfo)
- {
- foreach (IModuleTypeLoader typeLoader in this.ModuleTypeLoaders)
- {
- if (typeLoader.CanLoadModuleType(moduleInfo))
- {
- return typeLoader;
- }
- }
-
- throw new ModuleTypeLoaderNotFoundException(moduleInfo.ModuleName, String.Format(CultureInfo.CurrentCulture, Resources.NoRetrieverCanRetrieveModule, moduleInfo.ModuleName), null);
- }
-
- private void InitializeModule(ModuleInfo moduleInfo)
- {
- if (moduleInfo.State == ModuleState.Initializing)
- {
- this.moduleInitializer.Initialize(moduleInfo);
- moduleInfo.State = ModuleState.Initialized;
- }
- }
- }
- }