public void ModifiesFolders() { // Given FileSystem fileSystem = new FileSystem { RootPath = @"C:/A", OutputPath = "C" }; fileSystem.InputPaths.Add("B"); PackagesCollection packages = new PackagesCollection(fileSystem); AssemblyCollection assemblies = new AssemblyCollection(); string setup = @" FileSystem.RootPath = @""C:\X""; FileSystem.InputPaths.Add(""Y""); FileSystem.OutputPath = ""Z""; "; SetupScript setupScript = new SetupScript(setup); setupScript.Compile(); // When setupScript.Invoke(packages, assemblies, fileSystem); // Then Assert.AreEqual(@"C:/X", fileSystem.RootPath.FullPath); Assert.AreEqual(@"Z", fileSystem.OutputPath.FullPath); CollectionAssert.AreEquivalent(new[] { "input", "B", "Y" }, fileSystem.InputPaths.Select(x => x.FullPath)); }
// Adds all specified assemblies and those in packages path, finds all modules, and adds their namespaces and all assembly references to the options public void Initialize(AssemblyCollection assemblyCollection, PackagesCollection packages, IReadOnlyFileSystem fileSystem) { // Add all module namespaces from Wyam.Core _namespaces.AddRange(typeof(Engine).Assembly.GetTypes() .Where(x => typeof(IModule).IsAssignableFrom(x)) .Select(x => x.Namespace)); // Also include all Wyam.Common namespaces _namespaces.AddRange(typeof(IModule).Assembly.GetTypes() .Where(x => !string.IsNullOrWhiteSpace(x.Namespace)) .Select(x => x.Namespace)); // Get path to all assemblies (except those specified by name) List <string> assemblyPaths = new List <string>(); assemblyPaths.AddRange(packages.GetCompatibleAssemblyPaths()); assemblyPaths.AddRange(Directory.GetFiles(System.IO.Path.GetDirectoryName(typeof(Config).Assembly.Location), "*.dll", SearchOption.AllDirectories)); assemblyPaths.AddRange(assemblyCollection.Directories .Select(x => new Tuple <string, SearchOption>(System.IO.Path.Combine(fileSystem.RootPath.FullPath, x.Item1), x.Item2)) .Where(x => Directory.Exists(x.Item1)) .SelectMany(x => Directory.GetFiles(x.Item1, "*.dll", x.Item2))); assemblyPaths.AddRange(assemblyCollection.ByFile .Select(x => new Tuple <string, string>(x, System.IO.Path.Combine(fileSystem.RootPath.FullPath, x))) .Select(x => File.Exists(x.Item2) ? x.Item2 : x.Item1)); // Add all paths to the PrivateBinPath search location (to ensure they load in the default context) AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = string.Join(";", new[] { AppDomain.CurrentDomain.SetupInformation.PrivateBinPath } .Concat(assemblyPaths.Select(x => System.IO.Path.GetDirectoryName(x).Distinct()))); // Iterate assemblies by path (making sure to add them to the current path if relative), add them to the script, and check for modules // If this approach causes problems, could also try loading assemblies in custom app domain: // http://stackoverflow.com/questions/6626647/custom-appdomain-and-privatebinpath foreach (string assemblyPath in assemblyPaths.Distinct()) { try { Trace.Verbose("Loading assembly file {0}", assemblyPath); AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath); Assembly assembly = Assembly.Load(assemblyName); if (!AddAssembly(assembly)) { Trace.Verbose("Skipping assembly file {0} because it was already added", assemblyPath); } else { LoadReferencedAssemblies(assembly.GetReferencedAssemblies()); } } catch (Exception ex) { Trace.Verbose("{0} exception while loading assembly file {1}: {2}", ex.GetType().Name, assemblyPath, ex.Message); } } // Also iterate assemblies specified by name foreach (string assemblyName in assemblyCollection.ByName) { try { Trace.Verbose("Loading assembly {0}", assemblyName); Assembly assembly = Assembly.Load(assemblyName); if (!AddAssembly(assembly)) { Trace.Verbose("Skipping assembly {0} because it was already added", assemblyName); } else { LoadReferencedAssemblies(assembly.GetReferencedAssemblies()); } } catch (Exception ex) { Trace.Verbose("{0} exception while loading assembly {1}: {2}", ex.GetType().Name, assemblyName, ex.Message); } } }
// Adds all specified assemblies and those in packages path, finds all modules, and adds their namespaces and all assembly references to the options public void Initialize(AssemblyCollection assemblyCollection, PackagesCollection packages, IFileSystem fileSystem) { // Add all module namespaces from Wyam.Core _namespaces.AddRange(typeof(Engine).Assembly.GetTypes() .Where(x => typeof(IModule).IsAssignableFrom(x)) .Select(x => x.Namespace)); // Also include all Wyam.Common namespaces _namespaces.AddRange(typeof(IModule).Assembly.GetTypes() .Where(x => !string.IsNullOrWhiteSpace(x.Namespace)) .Select(x => x.Namespace)); // Get path to all assemblies (except those specified by name) List<string> assemblyPaths = new List<string>(); assemblyPaths.AddRange(packages.GetCompatibleAssemblyPaths()); assemblyPaths.AddRange(Directory.GetFiles(System.IO.Path.GetDirectoryName(typeof(Config).Assembly.Location), "*.dll", SearchOption.AllDirectories)); assemblyPaths.AddRange(assemblyCollection.Directories .Select(x => new Tuple<string, SearchOption>(System.IO.Path.Combine(fileSystem.RootPath.FullPath, x.Item1), x.Item2)) .Where(x => Directory.Exists(x.Item1)) .SelectMany(x => Directory.GetFiles(x.Item1, "*.dll", x.Item2))); assemblyPaths.AddRange(assemblyCollection.ByFile .Select(x => new Tuple<string, string>(x, System.IO.Path.Combine(fileSystem.RootPath.FullPath, x))) .Select(x => File.Exists(x.Item2) ? x.Item2 : x.Item1)); // Add all paths to the PrivateBinPath search location (to ensure they load in the default context) AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = string.Join(";", new[] { AppDomain.CurrentDomain.SetupInformation.PrivateBinPath } .Concat(assemblyPaths.Select(x => System.IO.Path.GetDirectoryName(x).Distinct()))); // Iterate assemblies by path (making sure to add them to the current path if relative), add them to the script, and check for modules // If this approach causes problems, could also try loading assemblies in custom app domain: // http://stackoverflow.com/questions/6626647/custom-appdomain-and-privatebinpath foreach (string assemblyPath in assemblyPaths.Distinct()) { try { Trace.Verbose("Loading assembly file {0}", assemblyPath); AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath); Assembly assembly = Assembly.Load(assemblyName); if (!AddAssembly(assembly)) { Trace.Verbose("Skipping assembly file {0} because it was already added", assemblyPath); } else { LoadReferencedAssemblies(assembly.GetReferencedAssemblies()); } } catch (Exception ex) { Trace.Verbose("{0} exception while loading assembly file {1}: {2}", ex.GetType().Name, assemblyPath, ex.Message); } } // Also iterate assemblies specified by name foreach (string assemblyName in assemblyCollection.ByName) { try { Trace.Verbose("Loading assembly {0}", assemblyName); Assembly assembly = Assembly.Load(assemblyName); if (!AddAssembly(assembly)) { Trace.Verbose("Skipping assembly {0} because it was already added", assemblyName); } else { LoadReferencedAssemblies(assembly.GetReferencedAssemblies()); } } catch (Exception ex) { Trace.Verbose("{0} exception while loading assembly {1}: {2}", ex.GetType().Name, assemblyName, ex.Message); } } }