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

Commit

Permalink
Merge pull request #959 from thecodejunkie/applicationregistationsbase
Browse files Browse the repository at this point in the history
Added ApplicationRegistrations base class
  • Loading branch information
thecodejunkie committed Feb 11, 2013
2 parents d663832 + 955fd7c commit 4b28703
Show file tree
Hide file tree
Showing 12 changed files with 354 additions and 49 deletions.
1 change: 0 additions & 1 deletion src/Nancy.Demo.Hosting.Aspnet/DemoBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ protected override void ConfigureApplicationContainer(TinyIoCContainer existingC
// We don't call base because we don't want autoregister
// we just register our one known dependency as an application level singleton
existingContainer.Register<IApplicationDependency, ApplicationDependencyClass>().AsSingleton();
existingContainer.Register<IRazorConfiguration, MyRazorConfiguration>().AsSingleton();
}

protected override void ConfigureRequestContainer(TinyIoCContainer existingContainer, NancyContext context)
Expand Down
2 changes: 2 additions & 0 deletions src/Nancy.Tests/Nancy.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@
<Compile Include="Fakes\MockPipelines.cs" />
<Compile Include="Fakes\Person.cs" />
<Compile Include="Fakes\ViewModel.cs" />
<Compile Include="Unit\Bootstrapper\CollectionTypeRegistrationFixture.cs" />
<Compile Include="Unit\Bootstrapper\InstanceRegistrationFixture.cs" />
<Compile Include="Unit\Bootstrapper\PipelinesFixture.cs" />
<Compile Include="Unit\Conventions\DefaultAcceptHeaderCoercionConventionsFixture.cs" />
<Compile Include="Unit\Conventions\DefaultCultureConventionsFixture.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace Nancy.Tests.Unit.Bootstrapper
{
using System;
using Nancy.Bootstrapper;
using Nancy.Responses.Negotiation;
using Xunit;

public class CollectionTypeRegistrationFixture
{
[Fact]
public void Should_throw_if_registration_type_is_null()
{
// Given, When
var result = Record.Exception(() => new CollectionTypeRegistration(null, new[] { typeof(object) }));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_implementation_types_is_null()
{
// Given, When
var result = Record.Exception(() => new CollectionTypeRegistration(typeof(object), null));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_not_all_implementation_types_does_implement_registration_type()
{
// Given, When
var result = Record.Exception(() => new CollectionTypeRegistration(typeof(IResponseProcessor), new[] { typeof(XmlProcessor), typeof(DefaultNancyBootstrapper) }));

// Then
result.ShouldBeOfType(typeof(ArgumentException));
}

[Fact]
public void Should_not_throw_if_all_implementation_types_implements_registration_type()
{
// Given, When
var result = Record.Exception(() => new CollectionTypeRegistration(typeof(IResponseProcessor), new[] { typeof(XmlProcessor), typeof(JsonProcessor) }));

// Then
result.ShouldBeNull();
}
}
}
49 changes: 49 additions & 0 deletions src/Nancy.Tests/Unit/Bootstrapper/InstanceRegistrationFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace Nancy.Tests.Unit.Bootstrapper
{
using System;
using Nancy.Bootstrapper;
using Xunit;

public class InstanceRegistrationFixture
{
[Fact]
public void Should_throw_if_registration_type_is_null()
{
// Given, When
var result = Record.Exception(() => new InstanceRegistration(null, new object()));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_implementation_is_null()
{
// Given, When
var result = Record.Exception(() => new InstanceRegistration(typeof(object), null));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_implementation_instance_does_not_implement_registration_type()
{
// Given, When
var result = Record.Exception(() => new InstanceRegistration(typeof(INancyBootstrapper), new object()));

// Then
result.ShouldBeOfType(typeof(ArgumentException));
}

[Fact]
public void Should_not_throw_if_implementation_instance_implements_registration_type()
{
// Given, When
var result = Record.Exception(() => new InstanceRegistration(typeof(INancyBootstrapper), new DefaultNancyBootstrapper()));

// Then
result.ShouldBeNull();
}
}
}
10 changes: 8 additions & 2 deletions src/Nancy.Tests/Unit/Bootstrapper/TypeRegistrationFixture.cs
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
namespace Nancy.Tests.Unit.Bootstrapper
{
using System;

using Nancy.Bootstrapper;

using Xunit;

public class TypeRegistrationFixture
{
[Fact]
public void Should_throw_if_registration_type_null()
{
// Given, When
var result = Record.Exception(() => new TypeRegistration(null, typeof(object)));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_implementation_type_null()
{
// Given, When
var result = Record.Exception(() => new TypeRegistration(typeof(object), null));

// Then
result.ShouldBeOfType(typeof(ArgumentNullException));
}

[Fact]
public void Should_throw_if_implementation_type_does_not_implement_registration_type()
{
// Given, When
var result = Record.Exception(() => new TypeRegistration(typeof(INancyBootstrapper), typeof(object)));

// Then
result.ShouldBeOfType(typeof(ArgumentException));
}

[Fact]
public void Should_not_throw_if_implementation_type_implements_registration_type()
{
// Given, When
var result = Record.Exception(() => new TypeRegistration(typeof(INancyBootstrapper), typeof(DefaultNancyBootstrapper)));

// Then
result.ShouldBeNull();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
namespace Nancy.ViewEngines.Razor
{
using System.Collections.Generic;
using Bootstrapper;

/// <summary>
/// Default dependency registrations for the <see cref="RazorViewEngine"/> class.
/// </summary>
public class RazorViewEngineApplicationRegistrations : IApplicationRegistrations
public class RazorViewEngineApplicationRegistrations : ApplicationRegistrations
{
/// <summary>
/// Gets the type registrations to register for this startup task
/// </summary>
public IEnumerable<TypeRegistration> TypeRegistrations
public RazorViewEngineApplicationRegistrations()
{
get { return new[] { new TypeRegistration(typeof(IRazorConfiguration), typeof(DefaultRazorConfiguration)), }; }
}

/// <summary>
/// Gets the collection registrations to register for this startup task
/// </summary>
public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations
{
get { return null; }
}

/// <summary>
/// Gets the instance registrations to register for this startup task
/// </summary>
public IEnumerable<InstanceRegistration> InstanceRegistrations
{
get { return null; }
this.RegisterWithDefault<IRazorConfiguration>(typeof(DefaultRazorConfiguration));
}
}
}
176 changes: 176 additions & 0 deletions src/Nancy/Bootstrapper/ApplicationRegistrations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
namespace Nancy.Bootstrapper
{
using System;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// Helper class for providing application registrations
/// </summary>
public abstract class ApplicationRegistrations : IApplicationRegistrations
{
private readonly IList<CollectionTypeRegistration> collectionRegistrations = new List<CollectionTypeRegistration>();
private readonly IList<InstanceRegistration> instanceRegistrations = new List<InstanceRegistration>();
private readonly IList<TypeRegistration> typeRegistrations = new List<TypeRegistration>();

/// <summary>
/// Gets the collection registrations to register for this startup task
/// </summary>
public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations
{
get { return this.collectionRegistrations; }
}

/// <summary>
/// Gets the instance registrations to register for this startup task
/// </summary>
public IEnumerable<InstanceRegistration> InstanceRegistrations
{
get { return this.instanceRegistrations; }
}

/// <summary>
/// Gets the type registrations to register for this startup task
/// </summary>
public IEnumerable<TypeRegistration> TypeRegistrations
{
get { return this.typeRegistrations; }
}

/// <summary>
/// Scans for the implementation of <typeparamref name="T"/> and registers it.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to scan for and register as.</typeparam>
public void Register<TRegistration>()
{
var implementation = AppDomainAssemblyTypeScanner
.TypesOf<TRegistration>()
.Single();

this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
}

/// <summary>
/// Registers the types provided by the <paramref name="defaultImplementations"/> parameters
/// as <typeparamref name="TRegistration"/>.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="defaultImplementations">The types to register.</param>
public void Register<TRegistration>(IEnumerable<Type> defaultImplementations)
{
this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), defaultImplementations));
}

/// <summary>
/// Registers the type provided by the <paramref name="implementation"/> parameter
/// as <typeparamref name="TRegistration"/>.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="implementation">The <see cref="Type"/> to register as <typeparamref name="TRegistration"/>.</param>
public void Register<TRegistration>(Type implementation)
{
this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
}

/// <summary>
/// Registers an instance as <typeparamref name="TRegistration"/>.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="instance">The instance to register.</param>
public void Register<TRegistration>(TRegistration instance)
{
this.instanceRegistrations.Add(new InstanceRegistration(typeof(TRegistration), instance));
}

/// <summary>
/// Scans for a <see cref="Type"/> that implements <typeparamref name="TRegistration"/>. If found, then it
/// will be used for the registration, else it will use <paramref name="defaultImplementation"/>.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="defaultImplementation">The implementation of <typeparamref name="TRegistration"/> that will be use if no other implenmentation can be found.</param>
/// <remarks>
/// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
/// the type specified by <paramref name="defaultImplementation"/>.
/// </remarks>
public void RegisterWithDefault<TRegistration>(Type defaultImplementation)
{
var implementation = AppDomainAssemblyTypeScanner
.TypesOf<TRegistration>()
.Where(type => type.Assembly != this.GetType().Assembly)
.SingleOrDefault(type => type != defaultImplementation);

this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation ?? defaultImplementation));
}

/// <summary>
/// Scans for an implementation of <typeparamref name="TRegistration"/> and registers it if found. If no implementation could
/// be found, it will retrieve an instance of <typeparamref name="TRegistration"/> using the provided <paramref name="defaultImplementationFactory"/>,
/// which will be used in the registration.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="defaultImplementationFactory">Factory that provides an instance of <typeparamref name="TRegistration"/>.</param>
/// <remarks>When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in</remarks>
public void RegisterWithDefault<TRegistration>(Func<TRegistration> defaultImplementationFactory)
{
var implementation = AppDomainAssemblyTypeScanner
.TypesOf<TRegistration>()
.SingleOrDefault(type => type.Assembly != this.GetType().Assembly);

if (implementation != null)
{
this.typeRegistrations.Add(new TypeRegistration(typeof(TRegistration), implementation));
}
else
{
this.instanceRegistrations.Add(new InstanceRegistration(typeof(TRegistration), defaultImplementationFactory.Invoke()));
}
}

/// <summary>
/// Scans for all implementations of <typeparamref name="TRegistration"/>. If no implementations could be found, then it
/// will register the types specified by <paramref name="defaultImplementations"/>.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="defaultImplementations">The types to register if non could be located while scanning.</param>
/// <remarks>
/// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
/// the types specified by <paramref name="defaultImplementations"/>.
/// </remarks>
public void RegisterWithDefault<TRegistration>(IEnumerable<Type> defaultImplementations)
{
var implementations = AppDomainAssemblyTypeScanner
.TypesOf<TRegistration>()
.Where(type => type.Assembly != this.GetType().Assembly)
.Where(type => !defaultImplementations.Contains(type))
.ToList();

if (!implementations.Any())
{
implementations = defaultImplementations.ToList();
}

this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), implementations));
}

/// <summary>
/// Scans for all implementations of <typeparamref name="TRegistration"/> and registers them, followed by the
/// types defined by the <paramref name="defaultImplementations"/> parameter.
/// </summary>
/// <typeparam name="TRegistration">The <see cref="Type"/> to register as.</typeparam>
/// <param name="defaultImplementations">The types to register last.</param>
/// <remarks>
/// When scanning, it will exclude the assembly that the <see cref="ApplicationRegistrations"/> instance is defined in and it will also ignore
/// the types specified by <paramref name="defaultImplementations"/>.
/// </remarks>
public void RegisterWithUserThenDefault<TRegistration>(IEnumerable<Type> defaultImplementations)
{
var implementations = AppDomainAssemblyTypeScanner
.TypesOf<TRegistration>()
.Where(type => type.Assembly != this.GetType().Assembly)
.Where(type => !defaultImplementations.Contains(type))
.ToList();

this.collectionRegistrations.Add(new CollectionTypeRegistration(typeof(TRegistration), implementations.Union(defaultImplementations)));
}
}
}
Loading

0 comments on commit 4b28703

Please sign in to comment.