Skip to content
This repository

Added ApplicationRegistrations base class #959

Merged
merged 6 commits into from over 1 year ago

2 participants

Andreas Håkansson Steven Robbins
Andreas Håkansson

Can be used to register application dependencies, with fallbacks and order

Steven Robbins grumpydev commented on the diff
src/Nancy/Bootstrapper/ApplicationRegistrations.cs
((33 lines not shown))
  33 + /// Gets the type registrations to register for this startup task
  34 + /// </summary>
  35 + public IEnumerable<TypeRegistration> TypeRegistrations
  36 + {
  37 + get { return this.typeRegistrations; }
  38 + }
  39 +
  40 + /// <summary>
  41 + /// Scans for the implementation of <typeparamref name="T"/> and registers it.
  42 + /// </summary>
  43 + /// <typeparam name="TRegistration">The <see cref="Type"/> to scan for and register as.</typeparam>
  44 + public void Register<TRegistration>()
  45 + {
  46 + var implementation = AppDomainAssemblyTypeScanner
  47 + .TypesOf<TRegistration>()
  48 + .Single();
1
Steven Robbins Owner

Do we actually want to blow up here if there's more than one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Steven Robbins grumpydev commented on the diff
src/Nancy/Bootstrapper/ApplicationRegistrations.cs
... ... @@ -0,0 +1,176 @@
  1 +namespace Nancy.Bootstrapper
  2 +{
  3 + using System;
1
Steven Robbins Owner

Using statements should be inside the namespace ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Steven Robbins grumpydev commented on the diff
src/Nancy/Bootstrapper/ApplicationRegistrations.cs
((46 lines not shown))
  46 + var implementation = AppDomainAssemblyTypeScanner
  47 + .TypesOf<TRegistration>()
  48 + .Single();
  49 +
  50 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
  51 + }
  52 +
  53 + /// <summary>
  54 + /// Registers the types provided by the <paramref name="defaultImplementations"/> parameters
  55 + /// as <typeparamref name="TRegistration"/>.
  56 + /// </summary>
  57 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  58 + /// <param name="defaultImplementations">The types to register.</param>
  59 + public void Register<TRegistration>(IEnumerable<Type> defaultImplementations)
  60 + {
  61 + this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), defaultImplementations));
1
Steven Robbins Owner

Add a check that all types are actually implementations of TRegistration? OR maybe add that code to CollectionTypeRegistration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Steven Robbins grumpydev commented on the diff
src/Nancy/Bootstrapper/ApplicationRegistrations.cs
((57 lines not shown))
  57 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  58 + /// <param name="defaultImplementations">The types to register.</param>
  59 + public void Register<TRegistration>(IEnumerable<Type> defaultImplementations)
  60 + {
  61 + this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), defaultImplementations));
  62 + }
  63 +
  64 + /// <summary>
  65 + /// Registers the type provided by the <paramref name="implementation"/> parameter
  66 + /// as <typeparamref name="TRegistration"/>.
  67 + /// </summary>
  68 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  69 + /// <param name="implementation">The <see cref="Type"/> to register as <typeparamref name="TRegistration"/>.</param>
  70 + public void Register<TRegistration>(Type implementation)
  71 + {
  72 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
1
Steven Robbins Owner

Ditto with the checks on other types of registrations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Nancy/Bootstrapper/ApplicationRegistrations.cs
((72 lines not shown))
  72 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
  73 + }
  74 +
  75 + /// <summary>
  76 + /// Registers an instance as <typeparamref name="TRegistration"/>.
  77 + /// </summary>
  78 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  79 + /// <param name="instance">The instance to register.</param>
  80 + public void Register<TRegistration>(TRegistration instance)
  81 + {
  82 + this.instanceRegistrations.Add(new InstanceRegistration(typeof(TRegistration), instance));
  83 + }
  84 +
  85 + /// <summary>
  86 + /// Scans for a <see cref="Type"/> that implements <typeparamref name="TRegistration"/>. If found, then it
  87 + /// will be used for the registartion, else it will use <paramref name="defaultImplementation"/>.
1
Steven Robbins Owner

Typo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Andreas Håkansson thecodejunkie merged commit 4b28703 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 6 unique commits by 1 author.

Feb 08, 2013
Andreas Håkansson thecodejunkie Added application registation base e7c2191
Andreas Håkansson thecodejunkie Tweaked base class 8880368
Andreas Håkansson thecodejunkie Updated razor registrations to support overriding 20be161
Andreas Håkansson thecodejunkie Removed explicit razor configuration registrations from demo project 57b0fd9
Feb 10, 2013
Andreas Håkansson thecodejunkie Made registration classes check types
Will throw (with detailed error message) if any of the
implementing types is not assignable from the registration
type.

Also added unit test coverage
2248afd
Andreas Håkansson thecodejunkie Fixed typo 955fd7c
This page is out of date. Refresh to see the latest.
1  src/Nancy.Demo.Hosting.Aspnet/DemoBootstrapper.cs
@@ -26,7 +26,6 @@ protected override void ConfigureApplicationContainer(TinyIoCContainer existingC
26 26 // We don't call base because we don't want autoregister
27 27 // we just register our one known dependency as an application level singleton
28 28 existingContainer.Register<IApplicationDependency, ApplicationDependencyClass>().AsSingleton();
29   - existingContainer.Register<IRazorConfiguration, MyRazorConfiguration>().AsSingleton();
30 29 }
31 30
32 31 protected override void ConfigureRequestContainer(TinyIoCContainer existingContainer, NancyContext context)
2  src/Nancy.Tests/Nancy.Tests.csproj
@@ -128,6 +128,8 @@
128 128 <Compile Include="Fakes\MockPipelines.cs" />
129 129 <Compile Include="Fakes\Person.cs" />
130 130 <Compile Include="Fakes\ViewModel.cs" />
  131 + <Compile Include="Unit\Bootstrapper\CollectionTypeRegistrationFixture.cs" />
  132 + <Compile Include="Unit\Bootstrapper\InstanceRegistrationFixture.cs" />
131 133 <Compile Include="Unit\Bootstrapper\PipelinesFixture.cs" />
132 134 <Compile Include="Unit\Conventions\DefaultAcceptHeaderCoercionConventionsFixture.cs" />
133 135 <Compile Include="Unit\Conventions\DefaultCultureConventionsFixture.cs" />
50 src/Nancy.Tests/Unit/Bootstrapper/CollectionTypeRegistrationFixture.cs
... ... @@ -0,0 +1,50 @@
  1 +namespace Nancy.Tests.Unit.Bootstrapper
  2 +{
  3 + using System;
  4 + using Nancy.Bootstrapper;
  5 + using Nancy.Responses.Negotiation;
  6 + using Xunit;
  7 +
  8 + public class CollectionTypeRegistrationFixture
  9 + {
  10 + [Fact]
  11 + public void Should_throw_if_registration_type_is_null()
  12 + {
  13 + // Given, When
  14 + var result = Record.Exception(() => new CollectionTypeRegistration(null, new[] { typeof(object) }));
  15 +
  16 + // Then
  17 + result.ShouldBeOfType(typeof(ArgumentNullException));
  18 + }
  19 +
  20 + [Fact]
  21 + public void Should_throw_if_implementation_types_is_null()
  22 + {
  23 + // Given, When
  24 + var result = Record.Exception(() => new CollectionTypeRegistration(typeof(object), null));
  25 +
  26 + // Then
  27 + result.ShouldBeOfType(typeof(ArgumentNullException));
  28 + }
  29 +
  30 + [Fact]
  31 + public void Should_throw_if_not_all_implementation_types_does_implement_registration_type()
  32 + {
  33 + // Given, When
  34 + var result = Record.Exception(() => new CollectionTypeRegistration(typeof(IResponseProcessor), new[] { typeof(XmlProcessor), typeof(DefaultNancyBootstrapper) }));
  35 +
  36 + // Then
  37 + result.ShouldBeOfType(typeof(ArgumentException));
  38 + }
  39 +
  40 + [Fact]
  41 + public void Should_not_throw_if_all_implementation_types_implements_registration_type()
  42 + {
  43 + // Given, When
  44 + var result = Record.Exception(() => new CollectionTypeRegistration(typeof(IResponseProcessor), new[] { typeof(XmlProcessor), typeof(JsonProcessor) }));
  45 +
  46 + // Then
  47 + result.ShouldBeNull();
  48 + }
  49 + }
  50 +}
49 src/Nancy.Tests/Unit/Bootstrapper/InstanceRegistrationFixture.cs
... ... @@ -0,0 +1,49 @@
  1 +namespace Nancy.Tests.Unit.Bootstrapper
  2 +{
  3 + using System;
  4 + using Nancy.Bootstrapper;
  5 + using Xunit;
  6 +
  7 + public class InstanceRegistrationFixture
  8 + {
  9 + [Fact]
  10 + public void Should_throw_if_registration_type_is_null()
  11 + {
  12 + // Given, When
  13 + var result = Record.Exception(() => new InstanceRegistration(null, new object()));
  14 +
  15 + // Then
  16 + result.ShouldBeOfType(typeof(ArgumentNullException));
  17 + }
  18 +
  19 + [Fact]
  20 + public void Should_throw_if_implementation_is_null()
  21 + {
  22 + // Given, When
  23 + var result = Record.Exception(() => new InstanceRegistration(typeof(object), null));
  24 +
  25 + // Then
  26 + result.ShouldBeOfType(typeof(ArgumentNullException));
  27 + }
  28 +
  29 + [Fact]
  30 + public void Should_throw_if_implementation_instance_does_not_implement_registration_type()
  31 + {
  32 + // Given, When
  33 + var result = Record.Exception(() => new InstanceRegistration(typeof(INancyBootstrapper), new object()));
  34 +
  35 + // Then
  36 + result.ShouldBeOfType(typeof(ArgumentException));
  37 + }
  38 +
  39 + [Fact]
  40 + public void Should_not_throw_if_implementation_instance_implements_registration_type()
  41 + {
  42 + // Given, When
  43 + var result = Record.Exception(() => new InstanceRegistration(typeof(INancyBootstrapper), new DefaultNancyBootstrapper()));
  44 +
  45 + // Then
  46 + result.ShouldBeNull();
  47 + }
  48 + }
  49 +}
10 src/Nancy.Tests/Unit/Bootstrapper/TypeRegistrationFixture.cs
... ... @@ -1,9 +1,7 @@
1 1 namespace Nancy.Tests.Unit.Bootstrapper
2 2 {
3 3 using System;
4   -
5 4 using Nancy.Bootstrapper;
6   -
7 5 using Xunit;
8 6
9 7 public class TypeRegistrationFixture
@@ -11,32 +9,40 @@ public class TypeRegistrationFixture
11 9 [Fact]
12 10 public void Should_throw_if_registration_type_null()
13 11 {
  12 + // Given, When
14 13 var result = Record.Exception(() => new TypeRegistration(null, typeof(object)));
15 14
  15 + // Then
16 16 result.ShouldBeOfType(typeof(ArgumentNullException));
17 17 }
18 18
19 19 [Fact]
20 20 public void Should_throw_if_implementation_type_null()
21 21 {
  22 + // Given, When
22 23 var result = Record.Exception(() => new TypeRegistration(typeof(object), null));
23 24
  25 + // Then
24 26 result.ShouldBeOfType(typeof(ArgumentNullException));
25 27 }
26 28
27 29 [Fact]
28 30 public void Should_throw_if_implementation_type_does_not_implement_registration_type()
29 31 {
  32 + // Given, When
30 33 var result = Record.Exception(() => new TypeRegistration(typeof(INancyBootstrapper), typeof(object)));
31 34
  35 + // Then
32 36 result.ShouldBeOfType(typeof(ArgumentException));
33 37 }
34 38
35 39 [Fact]
36 40 public void Should_not_throw_if_implementation_type_implements_registration_type()
37 41 {
  42 + // Given, When
38 43 var result = Record.Exception(() => new TypeRegistration(typeof(INancyBootstrapper), typeof(DefaultNancyBootstrapper)));
39 44
  45 + // Then
40 46 result.ShouldBeNull();
41 47 }
42 48 }
26 src/Nancy.ViewEngines.Razor/RazorViewEngineApplicationStartupRegistrations.cs
... ... @@ -1,35 +1,15 @@
1 1 namespace Nancy.ViewEngines.Razor
2 2 {
3   - using System.Collections.Generic;
4 3 using Bootstrapper;
5 4
6 5 /// <summary>
7 6 /// Default dependency registrations for the <see cref="RazorViewEngine"/> class.
8 7 /// </summary>
9   - public class RazorViewEngineApplicationRegistrations : IApplicationRegistrations
  8 + public class RazorViewEngineApplicationRegistrations : ApplicationRegistrations
10 9 {
11   - /// <summary>
12   - /// Gets the type registrations to register for this startup task
13   - /// </summary>
14   - public IEnumerable<TypeRegistration> TypeRegistrations
  10 + public RazorViewEngineApplicationRegistrations()
15 11 {
16   - get { return new[] { new TypeRegistration(typeof(IRazorConfiguration), typeof(DefaultRazorConfiguration)), }; }
17   - }
18   -
19   - /// <summary>
20   - /// Gets the collection registrations to register for this startup task
21   - /// </summary>
22   - public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations
23   - {
24   - get { return null; }
25   - }
26   -
27   - /// <summary>
28   - /// Gets the instance registrations to register for this startup task
29   - /// </summary>
30   - public IEnumerable<InstanceRegistration> InstanceRegistrations
31   - {
32   - get { return null; }
  12 + this.RegisterWithDefault<IRazorConfiguration>(typeof(DefaultRazorConfiguration));
33 13 }
34 14 }
35 15 }
176 src/Nancy/Bootstrapper/ApplicationRegistrations.cs
... ... @@ -0,0 +1,176 @@
  1 +namespace Nancy.Bootstrapper
  2 +{
  3 + using System;
  4 + using System.Collections.Generic;
  5 + using System.Linq;
  6 +
  7 + /// <summary>
  8 + /// Helper class for providing application registrations
  9 + /// </summary>
  10 + public abstract class ApplicationRegistrations : IApplicationRegistrations
  11 + {
  12 + private readonly IList<CollectionTypeRegistration> collectionRegistrations = new List<CollectionTypeRegistration>();
  13 + private readonly IList<InstanceRegistration> instanceRegistrations = new List<InstanceRegistration>();
  14 + private readonly IList<TypeRegistration> typeRegistrations = new List<TypeRegistration>();
  15 +
  16 + /// <summary>
  17 + /// Gets the collection registrations to register for this startup task
  18 + /// </summary>
  19 + public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations
  20 + {
  21 + get { return this.collectionRegistrations; }
  22 + }
  23 +
  24 + /// <summary>
  25 + /// Gets the instance registrations to register for this startup task
  26 + /// </summary>
  27 + public IEnumerable<InstanceRegistration> InstanceRegistrations
  28 + {
  29 + get { return this.instanceRegistrations; }
  30 + }
  31 +
  32 + /// <summary>
  33 + /// Gets the type registrations to register for this startup task
  34 + /// </summary>
  35 + public IEnumerable<TypeRegistration> TypeRegistrations
  36 + {
  37 + get { return this.typeRegistrations; }
  38 + }
  39 +
  40 + /// <summary>
  41 + /// Scans for the implementation of <typeparamref name="T"/> and registers it.
  42 + /// </summary>
  43 + /// <typeparam name="TRegistration">The <see cref="Type"/> to scan for and register as.</typeparam>
  44 + public void Register<TRegistration>()
  45 + {
  46 + var implementation = AppDomainAssemblyTypeScanner
  47 + .TypesOf<TRegistration>()
  48 + .Single();
  49 +
  50 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
  51 + }
  52 +
  53 + /// <summary>
  54 + /// Registers the types provided by the <paramref name="defaultImplementations"/> parameters
  55 + /// as <typeparamref name="TRegistration"/>.
  56 + /// </summary>
  57 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  58 + /// <param name="defaultImplementations">The types to register.</param>
  59 + public void Register<TRegistration>(IEnumerable<Type> defaultImplementations)
  60 + {
  61 + this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), defaultImplementations));
  62 + }
  63 +
  64 + /// <summary>
  65 + /// Registers the type provided by the <paramref name="implementation"/> parameter
  66 + /// as <typeparamref name="TRegistration"/>.
  67 + /// </summary>
  68 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  69 + /// <param name="implementation">The <see cref="Type"/> to register as <typeparamref name="TRegistration"/>.</param>
  70 + public void Register<TRegistration>(Type implementation)
  71 + {
  72 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
  73 + }
  74 +
  75 + /// <summary>
  76 + /// Registers an instance as <typeparamref name="TRegistration"/>.
  77 + /// </summary>
  78 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  79 + /// <param name="instance">The instance to register.</param>
  80 + public void Register<TRegistration>(TRegistration instance)
  81 + {
  82 + this.instanceRegistrations.Add(new InstanceRegistration(typeof(TRegistration), instance));
  83 + }
  84 +
  85 + /// <summary>
  86 + /// Scans for a <see cref="Type"/> that implements <typeparamref name="TRegistration"/>. If found, then it
  87 + /// will be used for the registration, else it will use <paramref name="defaultImplementation"/>.
  88 + /// </summary>
  89 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  90 + /// <param name="defaultImplementation">The implementation of <typeparamref name="TRegistration"/> that will be use if no other implenmentation can be found.</param>
  91 + /// <remarks>
  92 + /// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
  93 + /// the type specified by <paramref name="defaultImplementation"/>.
  94 + /// </remarks>
  95 + public void RegisterWithDefault<TRegistration>(Type defaultImplementation)
  96 + {
  97 + var implementation = AppDomainAssemblyTypeScanner
  98 + .TypesOf<TRegistration>()
  99 + .Where(type => type.Assembly != this.GetType().Assembly)
  100 + .SingleOrDefault(type => type != defaultImplementation);
  101 +
  102 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation ?? defaultImplementation));
  103 + }
  104 +
  105 + /// <summary>
  106 + /// Scans for an implementation of <typeparamref name="TRegistration"/> and registers it if found. If no implementation could
  107 + /// be found, it will retrieve an instance of <typeparamref name="TRegistration"/> using the provided <paramref name="defaultImplementationFactory"/>,
  108 + /// which will be used in the registration.
  109 + /// </summary>
  110 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  111 + /// <param name="defaultImplementationFactory">Factory that provides an instance of <typeparamref name="TRegistration"/>.</param>
  112 + /// <remarks>When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in</remarks>
  113 + public void RegisterWithDefault<TRegistration>(Func<TRegistration> defaultImplementationFactory)
  114 + {
  115 + var implementation = AppDomainAssemblyTypeScanner
  116 + .TypesOf<TRegistration>()
  117 + .SingleOrDefault(type => type.Assembly != this.GetType().Assembly);
  118 +
  119 + if (implementation != null)
  120 + {
  121 + this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
  122 + }
  123 + else
  124 + {
  125 + this.instanceRegistrations.Add(new InstanceRegistration(typeof(TRegistration), defaultImplementationFactory.Invoke()));
  126 + }
  127 + }
  128 +
  129 + /// <summary>
  130 + /// Scans for all implementations of <typeparamref name="TRegistration"/>. If no implementations could be found, then it
  131 + /// will register the types specified by <paramref name="defaultImplementations"/>.
  132 + /// </summary>
  133 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  134 + /// <param name="defaultImplementations">The types to register if non could be located while scanning.</param>
  135 + /// <remarks>
  136 + /// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
  137 + /// the types specified by <paramref name="defaultImplementations"/>.
  138 + /// </remarks>
  139 + public void RegisterWithDefault<TRegistration>(IEnumerable<Type> defaultImplementations)
  140 + {
  141 + var implementations = AppDomainAssemblyTypeScanner
  142 + .TypesOf<TRegistration>()
  143 + .Where(type => type.Assembly != this.GetType().Assembly)
  144 + .Where(type => !defaultImplementations.Contains(type))
  145 + .ToList();
  146 +
  147 + if (!implementations.Any())
  148 + {
  149 + implementations = defaultImplementations.ToList();
  150 + }
  151 +
  152 + this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), implementations));
  153 + }
  154 +
  155 + /// <summary>
  156 + /// Scans for all implementations of <typeparamref name="TRegistration"/> and registers them, followed by the
  157 + /// types defined by the <paramref name="defaultImplementations"/> parameter.
  158 + /// </summary>
  159 + /// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
  160 + /// <param name="defaultImplementations">The types to register last.</param>
  161 + /// <remarks>
  162 + /// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
  163 + /// the types specified by <paramref name="defaultImplementations"/>.
  164 + /// </remarks>
  165 + public void RegisterWithUserThenDefault<TRegistration>(IEnumerable<Type> defaultImplementations)
  166 + {
  167 + var implementations = AppDomainAssemblyTypeScanner
  168 + .TypesOf<TRegistration>()
  169 + .Where(type => type.Assembly != this.GetType().Assembly)
  170 + .Where(type => !defaultImplementations.Contains(type))
  171 + .ToList();
  172 +
  173 + this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), implementations.Union(defaultImplementations)));
  174 + }
  175 + }
  176 +}
20 src/Nancy/Bootstrapper/CollectionTypeRegistration.cs
... ... @@ -1,6 +1,7 @@
1 1 namespace Nancy.Bootstrapper
2 2 {
3 3 using System;
  4 + using System.Linq;
4 5 using System.Collections.Generic;
5 6
6 7 /// <summary>
@@ -8,7 +9,7 @@ namespace Nancy.Bootstrapper
8 9 /// container to later be resolved using an IEnumerable{RegistrationType}
9 10 /// constructor dependency.
10 11 /// </summary>
11   - public class CollectionTypeRegistration
  12 + public class CollectionTypeRegistration : ContainerRegistration
12 13 {
13 14 /// <summary>
14 15 /// Represents a type to be registered multiple times into the
@@ -19,14 +20,21 @@ public class CollectionTypeRegistration
19 20 /// <param name="implementationTypes">Collection of implementation type i.e. MyClassThatImplementsIMyInterface</param>
20 21 public CollectionTypeRegistration(Type registrationType, IEnumerable<Type> implementationTypes)
21 22 {
  23 + if (registrationType == null)
  24 + {
  25 + throw new ArgumentNullException("registrationType");
  26 + }
  27 +
  28 + if (implementationTypes == null)
  29 + {
  30 + throw new ArgumentNullException("implementationTypes");
  31 + }
  32 +
22 33 this.RegistrationType = registrationType;
23 34 this.ImplementationTypes = implementationTypes;
24   - }
25 35
26   - /// <summary>
27   - /// Registration type i.e. IMyInterface
28   - /// </summary>
29   - public Type RegistrationType { get; private set; }
  36 + this.ValidateTypeCompatibility(implementationTypes.ToArray());
  37 + }
30 38
31 39 /// <summary>
32 40 /// Collection of implementation type i.e. MyClassThatImplementsIMyInterface
44 src/Nancy/Bootstrapper/ContainerRegistration.cs
... ... @@ -0,0 +1,44 @@
  1 +namespace Nancy.Bootstrapper
  2 +{
  3 + using System;
  4 + using System.Linq;
  5 +
  6 + /// <summary>
  7 + /// Base class for container registrations
  8 + /// </summary>
  9 + public abstract class ContainerRegistration
  10 + {
  11 + /// <summary>
  12 + /// Registration type i.e. IMyInterface
  13 + /// </summary>
  14 + public Type RegistrationType { get; protected set; }
  15 +
  16 + /// <summary>
  17 + /// Checks if all implementation types are assignable from the registration type, otherwise throws an exception.
  18 + /// </summary>
  19 + /// <param name="types">The implementation types.</param>
  20 + /// <exception cref="ArgumentException">One or more of the implementation types is not assignable from the registration type.</exception>
  21 + /// <exception cref="InvalidOperationException">The <see cref="RegistrationType"/> property must be assigned before the method is invoked.</exception>
  22 + protected void ValidateTypeCompatibility(params Type[] types)
  23 + {
  24 + if (this.RegistrationType == null)
  25 + {
  26 + throw new InvalidOperationException("The RegistrationType must be set first.");
  27 + }
  28 +
  29 + var incompatibleTypes =
  30 + types.Where(type => !this.RegistrationType.IsAssignableFrom(type)).ToArray();
  31 +
  32 + if (incompatibleTypes.Any())
  33 + {
  34 + var incompatibleTypeNames =
  35 + string.Join(", ", incompatibleTypes.Select(type => type.FullName));
  36 +
  37 + var errorMessage =
  38 + string.Format("{0} must implement {1} inorder to be registered by {2}", incompatibleTypeNames, this.RegistrationType.FullName, this.GetType().Name);
  39 +
  40 + throw new ArgumentException(errorMessage);
  41 + }
  42 + }
  43 + }
  44 +}
9 src/Nancy/Bootstrapper/InstanceRegistration.cs
@@ -5,7 +5,7 @@ namespace Nancy.Bootstrapper
5 5 /// <summary>
6 6 /// Represents an instance to be registered into the container
7 7 /// </summary>
8   - public class InstanceRegistration
  8 + public class InstanceRegistration : ContainerRegistration
9 9 {
10 10 /// <summary>
11 11 /// Initializes a new instance of the <see cref="InstanceRegistration"/> class.
@@ -26,16 +26,13 @@ public InstanceRegistration(Type registrationType, object implementation)
26 26
27 27 this.RegistrationType = registrationType;
28 28 this.Implementation = implementation;
  29 +
  30 + this.ValidateTypeCompatibility(implementation.GetType());
29 31 }
30 32
31 33 /// <summary>
32 34 /// Implementation object instance i.e. instance of MyClassThatImplementsIMyInterface
33 35 /// </summary>
34 36 public object Implementation { get; private set; }
35   -
36   - /// <summary>
37   - /// Registration type i.e. IMyInterface
38   - /// </summary>
39   - public Type RegistrationType { get; private set; }
40 37 }
41 38 }
14 src/Nancy/Bootstrapper/TypeRegistration.cs
@@ -5,7 +5,7 @@ namespace Nancy.Bootstrapper
5 5 /// <summary>
6 6 /// Represents a type to be registered into the container
7 7 /// </summary>
8   - public sealed class TypeRegistration
  8 + public sealed class TypeRegistration : ContainerRegistration
9 9 {
10 10 /// <summary>
11 11 /// Represents a type to be registered into the container
@@ -23,24 +23,16 @@ public TypeRegistration(Type registrationType, Type implementationType)
23 23 {
24 24 throw new ArgumentNullException("implementationType");
25 25 }
26   -
27   - if (!registrationType.IsAssignableFrom(implementationType))
28   - {
29   - throw new ArgumentException("implementationType must implement registrationType", "implementationType");
30   - }
31 26
32 27 this.RegistrationType = registrationType;
33 28 this.ImplementationType = implementationType;
  29 +
  30 + this.ValidateTypeCompatibility(implementationType);
34 31 }
35 32
36 33 /// <summary>
37 34 /// Implementation type i.e. MyClassThatImplementsIMyInterface
38 35 /// </summary>
39 36 public Type ImplementationType { get; private set; }
40   -
41   - /// <summary>
42   - /// Registration type i.e. IMyInterface
43   - /// </summary>
44   - public Type RegistrationType { get; private set; }
45 37 }
46 38 }
2  src/Nancy/Nancy.csproj
@@ -107,7 +107,9 @@
107 107 <Link>Properties\SharedAssemblyInfo.cs</Link>
108 108 </Compile>
109 109 <Compile Include="Bootstrapper\AppDomainAssemblyTypeScanner.cs" />
  110 + <Compile Include="Bootstrapper\ApplicationRegistrations.cs" />
110 111 <Compile Include="Bootstrapper\CollectionTypeRegistration.cs" />
  112 + <Compile Include="Bootstrapper\ContainerRegistration.cs" />
111 113 <Compile Include="Bootstrapper\FavIconApplicationStartup.cs" />
112 114 <Compile Include="Bootstrapper\IApplicationRegistrations.cs" />
113 115 <Compile Include="Bootstrapper\IPipelines.cs" />

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.