Skip to content
This repository was archived by the owner on Jan 24, 2021. It is now read-only.

Commit b41515f

Browse files
committed
Merge pull request #953 from grumpydev/ScanningChanges
Scanning changes
2 parents 176359e + 75a5e0e commit b41515f

11 files changed

+176
-135
lines changed

Diff for: src/Nancy.Testing.Tests/ConfigurableBootstrapperFixture.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,18 @@ public void Should_throw_exceptions_if_any_occur_in_route()
131131
public void Should_run_application_startup_closure()
132132
{
133133
var date = new DateTime(2112,10,31);
134-
var bootstrapper = new ConfigurableBootstrapper(with => with.ApplicationStartup((container, pipelines) =>
134+
135+
var bootstrapper = new ConfigurableBootstrapper(with =>
136+
{
137+
with.ApplicationStartup((container, pipelines) =>
135138
{
136139
pipelines.BeforeRequest += ctx =>
137140
{
138141
ctx.Items.Add("date", date);
139142
return null;
140143
};
141-
}));
144+
});
145+
});
142146

143147
bootstrapper.Initialise();
144148

Diff for: src/Nancy.Testing/ConfigurableBootstrapper.cs

+26-14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class ConfigurableBootstrapper : NancyBootstrapperWithRequestContainerBas
4141
/// </summary>
4242
public static IList<string> TestAssemblySuffixes = new[] { "test", "tests", "unittests", "specs", "specifications" };
4343

44+
private bool allDiscoveredModules;
45+
4446
/// <summary>
4547
/// Initializes a new instance of the <see cref="ConfigurableBootstrapper"/> class.
4648
/// </summary>
@@ -223,7 +225,12 @@ protected override IEnumerable<ModuleRegistration> Modules
223225
var moduleRegistrations =
224226
this.GetModuleRegistrations().ToList();
225227

226-
return (moduleRegistrations.Any()) ? moduleRegistrations : base.Modules;
228+
if (moduleRegistrations.Any())
229+
{
230+
return moduleRegistrations;
231+
}
232+
233+
return this.allDiscoveredModules ? base.Modules : new ModuleRegistration[] { };
227234
}
228235
}
229236

@@ -332,7 +339,16 @@ protected override TinyIoCContainer GetApplicationContainer()
332339
/// <returns>INancyEngine implementation</returns>
333340
protected override INancyEngine GetEngineInternal()
334341
{
335-
return this.ApplicationContainer.Resolve<INancyEngine>();
342+
try
343+
{
344+
return this.ApplicationContainer.Resolve<INancyEngine>();
345+
}
346+
catch (InvalidOperationException ex)
347+
{
348+
throw new InvalidOperationException(
349+
"Something went wrong when trying to satisfy one of the dependencies during composition, make sure that you've registered all new dependencies in the container and specified either a module to test, or set AllDiscoveredModules in the ConfigurableBootstrapper. Inspect the innerexception for more details.",
350+
ex.InnerException);
351+
}
336352
}
337353

338354
/// <summary>
@@ -536,6 +552,13 @@ public ConfigurableBootstrapperConfigurator(ConfigurableBootstrapper bootstrappe
536552
this.Diagnostics<DisabledDiagnostics>();
537553
}
538554

555+
public ConfigurableBootstrapperConfigurator AllDiscoveredModules()
556+
{
557+
this.bootstrapper.allDiscoveredModules = true;
558+
559+
return this;
560+
}
561+
539562
public ConfigurableBootstrapperConfigurator Binder(IBinder binder)
540563
{
541564
this.bootstrapper.registeredInstances.Add(
@@ -1620,17 +1643,6 @@ public ConfigurableBootstrapperConfigurator TrieNodeFactory<T>() where T : ITrie
16201643
return this;
16211644
}
16221645

1623-
/// <summary>
1624-
/// Configures the bootstrapper to add an assembly ignore predicate to the list
1625-
/// </summary>
1626-
/// <param name="ignoredPredicate">Ignore predicate</param>
1627-
/// <returns>A reference to the current <see cref="ConfigurableBootstrapperConfigurator"/>.</returns>
1628-
public ConfigurableBootstrapperConfigurator IgnoredAssembly(Func<Assembly, bool> ignoredPredicate)
1629-
{
1630-
this.bootstrapper.configuration.WithIgnoredAssembly(ignoredPredicate);
1631-
return this;
1632-
}
1633-
16341646
public ConfigurableBootstrapperConfigurator ApplicationStartup(Action<TinyIoCContainer, IPipelines> action)
16351647
{
16361648
this.bootstrapper.applicationStartupActions.Add(action);
@@ -1691,4 +1703,4 @@ public void RegisterModuleInstance(INancyModule module, string moduleKey)
16911703
}
16921704
}
16931705
}
1694-
}
1706+
}

Diff for: src/Nancy.Tests/Fakes/FakeDefaultNancyBootstrapper.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,16 @@ public FakeDefaultNancyBootstrapper()
2727

2828
}
2929

30+
protected override IEnumerable<Func<Assembly, bool>> AutoRegisterIgnoredAssemblies
31+
{
32+
get
33+
{
34+
return base.AutoRegisterIgnoredAssemblies.Union(new Func<Assembly, bool>[] { asm => asm.FullName.StartsWith("TestAssembly") });
35+
}
36+
}
3037
public FakeDefaultNancyBootstrapper(NancyInternalConfiguration configuration)
3138
{
32-
this.configuration = configuration.WithIgnoredAssembly(asm => asm.FullName.StartsWith("TestAssembly"));
33-
39+
this.configuration = configuration;
3440
this.RequestContainerInitialisations = new Dictionary<NancyContext, int>();
3541
}
3642

Diff for: src/Nancy.Tests/Unit/Bootstrapper/NancyBootstrapperBaseFixture.cs

-15
Original file line numberDiff line numberDiff line change
@@ -217,21 +217,6 @@ public void Should_register_application_registration_instance_registrations_into
217217
this.bootstrapper.InstanceRegistrations.ShouldBeSameAs(instanceRegistrations);
218218
}
219219

220-
[Fact]
221-
public void Should_ingore_assemblies_specified_in_AppDomainAssemblyTypeScanner()
222-
{
223-
// Given
224-
// When
225-
AppDomainAssemblyTypeScanner.IgnoredAssemblies =
226-
new Func<Assembly, bool>[]
227-
{
228-
asm => asm.FullName.StartsWith("mscorlib")
229-
};
230-
231-
// Then
232-
AppDomainAssemblyTypeScanner.TypesOf<IEnumerable>().Where(t => t.Assembly.FullName.StartsWith("mscorlib")).Count().ShouldEqual(0);
233-
}
234-
235220
[Fact]
236221
public void Should_allow_favicon_override()
237222
{

Diff for: src/Nancy.Tests/Unit/Bootstrapper/NancyInternalConfigurationFixture.cs

-22
Original file line numberDiff line numberDiff line change
@@ -66,27 +66,5 @@ public void Should_not_be_valid_if_any_types_null()
6666

6767
result.ShouldBeFalse();
6868
}
69-
70-
[Fact]
71-
public void Should_allow_additional_ignored_assemblies()
72-
{
73-
Func<Assembly, bool> predicate = asm => asm.FullName.StartsWith("moo");
74-
var config = NancyInternalConfiguration.Default.WithIgnoredAssembly(predicate);
75-
76-
var result = config.IgnoredAssemblies;
77-
78-
result.Any(p => p.Equals(predicate)).ShouldBeTrue();
79-
}
80-
81-
[Fact]
82-
public void Should_append_ignored_assembly_to_default()
83-
{
84-
Func<Assembly, bool> predicate = asm => asm.FullName.StartsWith("moo");
85-
var config = NancyInternalConfiguration.Default.WithIgnoredAssembly(predicate);
86-
87-
var result = config.IgnoredAssemblies.Count();
88-
89-
result.ShouldEqual(NancyInternalConfiguration.DefaultIgnoredAssemblies.Count() + 1);
90-
}
9169
}
9270
}

Diff for: src/Nancy.ViewEngines.Razor.Tests/RazorViewEngineFixture.cs

+17-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
using System.Dynamic;
55
using System.IO;
66
using System.Linq;
7+
using System.Reflection;
78
using System.Text;
9+
using System.Threading;
10+
811
using FakeItEasy;
9-
using Xunit;
12+
13+
using Nancy.Bootstrapper;
1014
using Nancy.Tests;
1115
using Nancy.ViewEngines.Razor.Tests.Models;
12-
using System.Threading;
13-
using Nancy.Localization;
16+
17+
using Xunit;
1418

1519
public class RazorViewEngineFixture
1620
{
@@ -156,6 +160,8 @@ public void RenderView_csharp_should_use_model_directive_for_strongly_typed_view
156160
[Fact]
157161
public void RenderView_csharp_should_be_able_to_use_a_model_from_another_assembly()
158162
{
163+
AppDomainAssemblyTypeScanner.AddAssembliesToScan("Nancy.ViewEngines.Razor.Tests.Models.dll");
164+
159165
// Given
160166
var view = new StringBuilder()
161167
.AppendLine("@model Nancy.ViewEngines.Razor.Tests.Models.Person")
@@ -183,6 +189,8 @@ public void RenderView_csharp_should_be_able_to_use_a_model_from_another_assembl
183189
[Fact]
184190
public void RenderView_csharp_should_be_able_to_use_a_using_statement()
185191
{
192+
AppDomainAssemblyTypeScanner.AddAssembliesToScan("Nancy.ViewEngines.Razor.Tests.Models");
193+
186194
// Given
187195
var view = new StringBuilder()
188196
.AppendLine("@model Nancy.ViewEngines.Razor.Tests.Models.Person")
@@ -213,6 +221,12 @@ public void RenderView_csharp_should_be_able_to_use_a_using_statement()
213221
public void RenderView_csharp_should_be_able_to_find_the_model_when_a_null_model_is_passed()
214222
{
215223
// Given
224+
AppDomainAssemblyTypeScanner.AssembliesToScan =
225+
AppDomainAssemblyTypeScanner.DefaultAssembliesToScan.Union(new Func<Assembly, bool>[]
226+
{
227+
x =>
228+
x.GetName().Name.StartsWith("Nancy")
229+
});
216230
var view = new StringBuilder()
217231
.AppendLine("@model Nancy.ViewEngines.Razor.Tests.Models.Person")
218232
.AppendLine(@"@{ var hobby = new Hobby { Name = ""Music"" }; }")

Diff for: src/Nancy/Bootstrapper/AppDomainAssemblyTypeScanner.cs

+84-8
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,35 @@ static AppDomainAssemblyTypeScanner()
3838
/// </summary>
3939
private static bool nancyAssembliesLoaded;
4040

41+
private static IEnumerable<Func<Assembly, bool>> assembliesToScan;
42+
4143
/// <summary>
42-
///
44+
/// The default assemblies for scanning.
45+
/// Includes the nancy assembly and anythign referencing a nancy assembly
4346
/// </summary>
44-
private static IEnumerable<Func<Assembly, bool>> ignoredAssemblies;
47+
public static Func<Assembly, bool>[] DefaultAssembliesToScan = new Func<Assembly, bool>[]
48+
{
49+
x => x == nancyAssembly,
50+
x => x.GetReferencedAssemblies().Any(r => r.Name.StartsWith("Nancy", StringComparison.OrdinalIgnoreCase))
51+
};
4552

4653
/// <summary>
47-
/// Gets or sets a set of rules for ignoring assemblies while scanning through them.
54+
/// Gets or sets a set of rules for which assemblies are scanned
55+
/// Defaults to just assemblies that have references to nancy, and nancy
56+
/// itself.
57+
/// Each item in the enumerable is a delegate that takes the assembly and
58+
/// returns true if it is to be included. Returning false doesn't mean it won't
59+
/// be included as a true from another delegate will take precedence.
4860
/// </summary>
49-
public static IEnumerable<Func<Assembly, bool>> IgnoredAssemblies
61+
public static IEnumerable<Func<Assembly, bool>> AssembliesToScan
5062
{
5163
private get
5264
{
53-
return ignoredAssemblies;
65+
return assembliesToScan ?? (assembliesToScan = DefaultAssembliesToScan);
5466
}
5567
set
5668
{
57-
ignoredAssemblies = value;
69+
assembliesToScan = value;
5870
UpdateTypes ();
5971
}
6072
}
@@ -81,6 +93,54 @@ public static IEnumerable<Assembly> Assemblies
8193
}
8294
}
8395

96+
/// <summary>
97+
/// Add assemblies to the list of assemblies to scan for Nancy types
98+
/// </summary>
99+
/// <param name="assemblyNames">One or more assembly names</param>
100+
public static void AddAssembliesToScan(params string[] assemblyNames)
101+
{
102+
var normalisedNames = GetNormalisedAssemblyNames(assemblyNames).ToArray();
103+
104+
foreach (var assemblyName in normalisedNames)
105+
{
106+
LoadAssemblies(assemblyName + ".dll");
107+
LoadAssemblies(assemblyName + ".exe");
108+
}
109+
110+
var scanningPredicates = normalisedNames.Select(s =>
111+
{
112+
return (Func<Assembly, bool>)(a => a.GetName().Name == s);
113+
});
114+
115+
AssembliesToScan = AssembliesToScan.Union(scanningPredicates);
116+
}
117+
118+
/// <summary>
119+
/// Add assemblies to the list of assemblies to scan for Nancy types
120+
/// </summary>
121+
/// <param name="assemblies">One of more assemblies</param>
122+
public static void AddAssembliesToScan(params Assembly[] assemblies)
123+
{
124+
foreach (var assembly in assemblies)
125+
{
126+
LoadAssemblies(assembly.GetName() + ".dll");
127+
LoadAssemblies(assembly.GetName() + ".exe");
128+
}
129+
130+
var scanningPredicates = assemblies.Select(an => (Func<Assembly, bool>)(a => a == an));
131+
132+
AssembliesToScan = AssembliesToScan.Union(scanningPredicates);
133+
}
134+
135+
/// <summary>
136+
/// Add predicates for determining which assemblies to scan for Nancy types
137+
/// </summary>
138+
/// <param name="predicates">One or more predicates</param>
139+
public static void AddAssembliesToScan(params Func<Assembly, bool>[] predicates)
140+
{
141+
AssembliesToScan = AssembliesToScan.Union(predicates);
142+
}
143+
84144
/// <summary>
85145
/// Load assemblies from a the app domain base directory matching a given wildcard.
86146
/// Assemblies will only be loaded if they aren't already in the appdomain.
@@ -108,7 +168,8 @@ public static void LoadAssemblies(string containingDirectory, string wildcardFil
108168

109169
var unloadedAssemblies =
110170
Directory.GetFiles(containingDirectory, wildcardFilename).Where(
111-
f => !existingAssemblyPaths.Contains(f, StringComparer.InvariantCultureIgnoreCase));
171+
f => !existingAssemblyPaths.Contains(f, StringComparer.InvariantCultureIgnoreCase)).ToArray();
172+
112173

113174
foreach (var unloadedAssembly in unloadedAssemblies)
114175
{
@@ -138,7 +199,7 @@ from type in assembly.SafeGetExportedTypes()
138199
private static void UpdateAssemblies()
139200
{
140201
assemblies = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
141-
where IgnoredAssemblies != null ? !IgnoredAssemblies.Any(asm => asm(assembly)) : true
202+
where AssembliesToScan.Any(asm => asm(assembly))
142203
where !assembly.IsDynamic
143204
where !assembly.ReflectionOnly
144205
select assembly).ToArray();
@@ -255,6 +316,21 @@ private static IEnumerable<string> GetAssemblyDirectories()
255316
yield return AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
256317
}
257318
}
319+
320+
private static IEnumerable<string> GetNormalisedAssemblyNames(string[] assemblyNames)
321+
{
322+
foreach (var assemblyName in assemblyNames)
323+
{
324+
if (assemblyName.EndsWith(".dll") || assemblyName.EndsWith(".exe"))
325+
{
326+
yield return Path.GetFileNameWithoutExtension(assemblyName);
327+
}
328+
else
329+
{
330+
yield return assemblyName;
331+
}
332+
}
333+
}
258334
}
259335

260336
public static class AppDomainAssemblyTypeScannerExtensions

Diff for: src/Nancy/Bootstrapper/NancyBootstrapperBase.cs

-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ protected virtual DiagnosticsConfiguration DiagnosticsConfiguration
209209
/// </summary>
210210
public void Initialise()
211211
{
212-
AppDomainAssemblyTypeScanner.IgnoredAssemblies = this.InternalConfiguration.IgnoredAssemblies;
213212
AppDomainAssemblyTypeScanner.LoadNancyAssemblies();
214213

215214
if (this.InternalConfiguration == null)

0 commit comments

Comments
 (0)