public virtual List <Tuple <Assembly, Type> > Start() { if (DependencyResolver.IsSet) { return(ModuleUtilities.GetLoadedModuleAssemblies(AppDomain.CurrentDomain.GetAssemblies())); } string binPath = GetBinPath(); IList <string> binDllFileNames = GetBinDllFileNames(binPath); List <ComposablePartCatalog> binComposablePartCatalogs = GetBinComposablePartCatalogs(binDllFileNames, binPath); CreateModuleDirectories(); //TODO: Auto Register (Convention parts mef...) Action Handlers //TODO: Auto Register Controllers insinde module content (metadata) avec un action handler sur la création d'un module? // Set Assembly Resolver (TODO : A quoi ca sert??? encore utile?? - je l'Enleve jusqu'a preuve du contraire...) //Apparament ca sert dans la génération des vues Razor.. si je l'enlève les vues ne sont pas générées!! //http://stackoverflow.com/questions/12128890/best-practices-for-composed-asp-net-mvc-web-applications-mef-areas-di //TODO: Si ca sert juste pour Razor il faudrait pas chercher dans tous les assemblies!? (performance) AppDomain.CurrentDomain.AssemblyResolve += new AssemblyResolver().CurrentDomainAssemblyResolve; // Pre Modules and Parts Composition //var composableParts = new List<ComposablePartCatalog> { new DirectoryCatalog(GetBinPath()) }; List <Assembly> allLoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies() .Where( a => !a.IsDynamic && binDllFileNames.Contains(Path.GetFileName(a.Location))) .ToList(); List <Tuple <Assembly, Type> > loadedModuleAssemblies = ModuleUtilities.GetLoadedModuleAssemblies(allLoadedAssemblies); //On crée un DependencyResolver temporaire pour aller chercher les IPartRegistryRetriever List <Assembly> moduleDirectoryAssemblies = CopyDllToExecutionPath(true, ref loadedModuleAssemblies, ref allLoadedAssemblies); foreach (var loadedModuleAssembly in loadedModuleAssemblies) { CreateModuleInitializerInstance(loadedModuleAssembly.Item2).PreInitialize(); } List <ComposablePartCatalog> allComposableParts = binComposablePartCatalogs.Union( moduleDirectoryAssemblies.Select( moduleDirectoryAssembly => new AssemblyCatalog(moduleDirectoryAssembly))).ToList(); IDependencyResolver dependencyResolver = GetDependencyResolver(allComposableParts); DependencyResolver.SetResolver(dependencyResolver); //Ajouter les conventions List <IPartRegistryRetriever> composablePartCatalogRetrievers = DependencyResolver.Current.GetServices <IPartRegistryRetriever>().ToList(); //PAs besoin de faire le join avec les modules assemblies car ils sont ajoutés a la collection allLoadedAssemblies //TODO: Rouler les conventions juste sur les module assemblies foreach (Assembly assembly in allLoadedAssemblies /*.Union(moduleDirectoryAssemblies).DistinctBy(a => a.FullName)*/) { //Attention si jamais on fait des conventions aussi dans LoadBinPartsAndSetTemporaryDependencyResolverForInitializationPeriod elles vont etre faites 2 fois... AddConventionParts(assembly, allComposableParts, composablePartCatalogRetrievers); } //Faire le DependencyResolver final (après conventions) dependencyResolver = GetDependencyResolver(allComposableParts); DependencyResolver.SetResolver(dependencyResolver); //On les fais tous d'u coup avec RavenDB - plus performant et limites de queries par défault InstallOrUpdateModules(loadedModuleAssemblies, dependencyResolver); InitializeModules(loadedModuleAssemblies, dependencyResolver); return(loadedModuleAssemblies); }
//TODO: Faire des tests et refactorer //TODO: Gérer les Framework Dependecies (dépendances a des dll du framework .net - on veut pas les ajouter au répertoire du module... il faudrait faire un autre fichier text pe et les charger...) protected virtual List <Assembly> CopyDllToExecutionPath(bool withCleanUp, ref List <Tuple <Assembly, Type> > loadedModuleAssemblies, ref List <Assembly> allLoadedAssemblies) { var moduleDirectoryAssemblies = new List <Assembly>(); // Clean and create Bin module path if (Directory.Exists(ModuleBinDirectoryPath) && withCleanUp) { SafeRemovePath(ModuleBinDirectoryPath); } string currentModulePathBinDirectory = CurrentModuleBinDirectoryPath; Directory.CreateDirectory(currentModulePathBinDirectory); // Modules Dll List <KeyValuePair <string, Tuple <FileInfo[], string[]> > > dllmodules = Directory.GetDirectories(ModuleDirectoryPath, "*.*", SearchOption.TopDirectoryOnly) .Select(dir => new DirectoryInfo(dir)) .Where(dir => !dir.Name.EndsWith(".svn")) .Where(dir => !dir.Name.EndsWith("Bin")) .Select( dir => new KeyValuePair <string, Tuple <FileInfo[], string[]> >(dir.Name, new Tuple <FileInfo[], string[]>( dir.GetFiles("*.dll"), GetModuleDependencies(dir)))) .Where(m => !IsFilteredOut(m)) .ToList(); //TODO: Refactorer... il se peut qu'on essaye d'ajouter un dll (dépendance d'un module) alors qu'on réfère déjà cette dépendence...! var notYetLoadedModules = new Dictionary <string, Tuple <FileInfo[], string[]> >(); var dependencyManager = new DependencyManager(); foreach (var mod in dllmodules) { Tuple <Assembly, Type> loaded = loadedModuleAssemblies.FirstOrDefault( q => q.Item1.GetName().Name.Equals(mod.Key, StringComparison.OrdinalIgnoreCase)); if (loaded == null) { notYetLoadedModules.Add(mod.Key, mod.Value); } dependencyManager.Add(mod.Key, mod.Value.Item2); } //TODO: Faire en sorte qu'une erreur précise découle d'une dépendences manquantes ou circulaire, etc.. IEnumerable <string> sortedDependencies = dependencyManager.GetSortedDependencies(); foreach (string sortedDependency in sortedDependencies) { Tuple <FileInfo[], string[]> module; notYetLoadedModules.TryGetValue(sortedDependency, out module); if (module != null) { List <FileInfo> dlls = module.Item1.ToList(); foreach (FileInfo dll in dlls) { string src = Path.Combine(currentModulePathBinDirectory, dll.Name); if (!File.Exists(src)) { File.Copy(dll.FullName, src); Assembly assembly = Assembly.LoadFile(src); allLoadedAssemblies.Add(assembly); } } Assembly moduleAssembly = allLoadedAssemblies.First(a => a.GetName().Name == sortedDependency); Type moduleInitializer = ModuleUtilities.GetModuleInitializerFromAssembly(moduleAssembly); loadedModuleAssemblies.Add(new Tuple <Assembly, Type>(moduleAssembly, moduleInitializer)); moduleDirectoryAssemblies.Add(moduleAssembly); } } return(moduleDirectoryAssemblies); }