From 59a279f590eeee328176bc53b216590db7040622 Mon Sep 17 00:00:00 2001 From: filipw Date: Sat, 7 Mar 2015 13:15:25 +0100 Subject: [PATCH 1/4] use reflection instead of MEF if we only need CSharp module --- src/ScriptCs.Hosting/ModuleLoader.cs | 36 +++++++++++++++++-- src/ScriptCs.Hosting/ScriptServicesBuilder.cs | 10 +++--- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/ScriptCs.Hosting/ModuleLoader.cs b/src/ScriptCs.Hosting/ModuleLoader.cs index c6ff0c1e..8781f821 100644 --- a/src/ScriptCs.Hosting/ModuleLoader.cs +++ b/src/ScriptCs.Hosting/ModuleLoader.cs @@ -12,6 +12,12 @@ namespace ScriptCs.Hosting { public class ModuleLoader : IModuleLoader { + private static Dictionary defaultCSharpModules = new Dictionary + { + {"roslyn", "ScriptCs.Engine.Roslyn.dll"}, + {"mono", "ScriptCs.Engine.Mono.dll"} + }; + private readonly IAssemblyResolver _resolver; private readonly ILog _logger; private readonly Action _addToCatalog; @@ -58,11 +64,35 @@ public ModuleLoader(IAssemblyResolver resolver, ILog logger, Action i))); + if (moduleNames.Length == 1) // only CSharp module needed + { + var csharpModuleAssembly = defaultCSharpModules[moduleNames[0]]; + var module = _assemblyUtility.LoadFile(Path.Combine(hostBin, csharpModuleAssembly)); + + if (module != null) + { + var moduleType = module.GetExportedTypes().FirstOrDefault(f => typeof (IModule).IsAssignableFrom(f)); + + if (moduleType != null) + { + var moduleInstance = Activator.CreateInstance(moduleType) as IModule; + + if (moduleInstance != null) + { + _logger.Debug(String.Format("Initializing module: {0}", module.GetType().FullName)); + moduleInstance.Initialize(config); + return; + } + } + } + } + + _logger.Debug("Loading modules from: " + String.Join(", ", modulePackagesPaths.Select(i => i))); var paths = new List(); AddPaths(modulePackagesPaths, hostBin, paths); @@ -91,7 +121,7 @@ private void InitializeModules( foreach (var module in modules) { - _logger.Debug(string.Format("Initializing module: {0}", module.GetType().FullName)); + _logger.Debug(String.Format("Initializing module: {0}", module.GetType().FullName)); module.Initialize(config); } diff --git a/src/ScriptCs.Hosting/ScriptServicesBuilder.cs b/src/ScriptCs.Hosting/ScriptServicesBuilder.cs index c794cd65..0901a490 100644 --- a/src/ScriptCs.Hosting/ScriptServicesBuilder.cs +++ b/src/ScriptCs.Hosting/ScriptServicesBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Common.Logging; using ScriptCs.Contracts; @@ -71,16 +72,17 @@ public ScriptServices Build() public IScriptServicesBuilder LoadModules(string extension, params string[] moduleNames) { var engineModule = _typeResolver.ResolveType("Mono.Runtime") != null || moduleNames.Contains("mono") - ? "mono" + ? "mono" : "roslyn"; - - moduleNames = moduleNames.Union(new[] { engineModule }).ToArray(); + + moduleNames = moduleNames.Union(new[] {engineModule}).ToArray(); + var config = new ModuleConfiguration(_cache, _scriptName, _repl, _logLevel, _debug, Overrides); var loader = InitializationServices.GetModuleLoader(); var fs = InitializationServices.GetFileSystem(); - var folders = new[] { fs.GlobalFolder }; + var folders = new[] {fs.GlobalFolder}; loader.Load(config, folders, InitializationServices.GetFileSystem().HostBin, extension, moduleNames); return this; } From af0a00dd96cd09b92ea168c6282b7237d36e8d6c Mon Sep 17 00:00:00 2001 From: filipw Date: Sat, 7 Mar 2015 13:27:55 +0100 Subject: [PATCH 2/4] loader clean up --- src/ScriptCs.Hosting/ModuleLoader.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ScriptCs.Hosting/ModuleLoader.cs b/src/ScriptCs.Hosting/ModuleLoader.cs index 8781f821..4b197b0d 100644 --- a/src/ScriptCs.Hosting/ModuleLoader.cs +++ b/src/ScriptCs.Hosting/ModuleLoader.cs @@ -12,7 +12,7 @@ namespace ScriptCs.Hosting { public class ModuleLoader : IModuleLoader { - private static Dictionary defaultCSharpModules = new Dictionary + private static readonly Dictionary DefaultCSharpModules = new Dictionary { {"roslyn", "ScriptCs.Engine.Roslyn.dll"}, {"mono", "ScriptCs.Engine.Mono.dll"} @@ -69,9 +69,10 @@ public void Load(IModuleConfiguration config, string[] modulePackagesPaths, stri { if (modulePackagesPaths == null) return; - if (moduleNames.Length == 1) // only CSharp module needed + if (moduleNames.Length == 1 && DefaultCSharpModules.ContainsKey(moduleNames[0])) // only CSharp module needed { - var csharpModuleAssembly = defaultCSharpModules[moduleNames[0]]; + _logger.Debug("Only CSharp module is needed - will skip module lookup"); + var csharpModuleAssembly = DefaultCSharpModules[moduleNames[0]]; var module = _assemblyUtility.LoadFile(Path.Combine(hostBin, csharpModuleAssembly)); if (module != null) From b2ad97d0a0b4b40fd5c42a66b15a2f130ffbfe38 Mon Sep 17 00:00:00 2001 From: filipw Date: Sat, 7 Mar 2015 14:09:18 +0100 Subject: [PATCH 3/4] added tests --- src/ScriptCs.Hosting/ModuleLoader.cs | 2 +- .../Properties/AssemblyInfo.cs | 3 ++ .../ModuleLoaderTests.cs | 34 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/ScriptCs.Hosting/ModuleLoader.cs b/src/ScriptCs.Hosting/ModuleLoader.cs index 4b197b0d..0f460596 100644 --- a/src/ScriptCs.Hosting/ModuleLoader.cs +++ b/src/ScriptCs.Hosting/ModuleLoader.cs @@ -12,7 +12,7 @@ namespace ScriptCs.Hosting { public class ModuleLoader : IModuleLoader { - private static readonly Dictionary DefaultCSharpModules = new Dictionary + internal static readonly Dictionary DefaultCSharpModules = new Dictionary { {"roslyn", "ScriptCs.Engine.Roslyn.dll"}, {"mono", "ScriptCs.Engine.Mono.dll"} diff --git a/src/ScriptCs.Hosting/Properties/AssemblyInfo.cs b/src/ScriptCs.Hosting/Properties/AssemblyInfo.cs index 27c64e7e..9aba106c 100644 --- a/src/ScriptCs.Hosting/Properties/AssemblyInfo.cs +++ b/src/ScriptCs.Hosting/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ using System.Reflection; +using System.Runtime.CompilerServices; [assembly: AssemblyTitle("ScriptCs.Hosting")] [assembly: AssemblyDescription("ScriptCs.Hosting provides common services necessary for hosting scriptcs in your application.")] + +[assembly: InternalsVisibleTo("ScriptCs.Hosting.Tests")] \ No newline at end of file diff --git a/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs b/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs index bdaf7088..789e6d94 100644 --- a/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs +++ b/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs @@ -9,6 +9,7 @@ using ScriptCs.Contracts; using Should; using Xunit; +using LogLevel = ScriptCs.Contracts.LogLevel; namespace ScriptCs.Hosting.Tests { @@ -110,6 +111,31 @@ public void ShouldNotInitializeModulesThatAreNotSetToAutoload() _mockModule1.Verify(m => m.Initialize(It.IsAny()), Times.Never()); } + [Fact] + public void ShouldLoadEngineAssemblyByHandIfItsTheOnlyModule() + { + var path = Path.Combine("c:\\foo", ModuleLoader.DefaultCSharpModules["roslyn"]); + _mockAssemblyUtility.Setup(x => x.LoadFile(path)); + var loader = new ModuleLoader(_mockAssemblyResolver.Object, _mockLogger.Object, (a, c) => { }, _getModules, _mockFileSystem.Object, _mockAssemblyUtility.Object); + loader.Load(null, new string[0], "c:\\foo", null, "roslyn"); + + _mockAssemblyUtility.Verify(x => x.LoadFile(path), Times.Once()); + } + + [Fact] + public void ShouldLoadEngineModuleFromFile() + { + var path = Path.Combine("c:\\foo", ModuleLoader.DefaultCSharpModules["roslyn"]); + _mockAssemblyUtility.Setup(x => x.LoadFile(It.IsAny())).Returns(typeof (DummyModule).Assembly); + var loader = new ModuleLoader(_mockAssemblyResolver.Object, _mockLogger.Object, (a, c) => { }, _getModules, _mockFileSystem.Object, _mockAssemblyUtility.Object); + + var config = new ModuleConfiguration(true, string.Empty, false, LogLevel.Debug, true, + new Dictionary {{typeof (string), "not loaded"}}); + loader.Load(config, new string[0], "c:\\foo", null, "roslyn"); + + config.Overrides[typeof(string)].ShouldEqual("module loaded"); + } + public class ModuleMetadata : IModuleMetadata { public string Name { get; set; } @@ -118,6 +144,14 @@ public class ModuleMetadata : IModuleMetadata public bool Autoload { get; set; } } + + public class DummyModule : IModule + { + public void Initialize(IModuleConfiguration config) + { + config.Overrides[typeof (string)] = "module loaded"; + } + } } } } From 563147e411356d2155997e7ca798a12c4aa69348 Mon Sep 17 00:00:00 2001 From: filipw Date: Sat, 7 Mar 2015 14:28:22 +0100 Subject: [PATCH 4/4] fixed travis build --- test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs b/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs index 789e6d94..8439162a 100644 --- a/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs +++ b/test/ScriptCs.Hosting.Tests/ModuleLoaderTests.cs @@ -125,7 +125,6 @@ public void ShouldLoadEngineAssemblyByHandIfItsTheOnlyModule() [Fact] public void ShouldLoadEngineModuleFromFile() { - var path = Path.Combine("c:\\foo", ModuleLoader.DefaultCSharpModules["roslyn"]); _mockAssemblyUtility.Setup(x => x.LoadFile(It.IsAny())).Returns(typeof (DummyModule).Assembly); var loader = new ModuleLoader(_mockAssemblyResolver.Object, _mockLogger.Object, (a, c) => { }, _getModules, _mockFileSystem.Object, _mockAssemblyUtility.Object);