Created
February 14, 2011 12:51
-
-
Save thecodejunkie/825827 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Nancy | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Nancy.ViewEngines; | |
using TinyIoC; | |
using Nancy.Bootstrapper; | |
/// <summary> | |
/// TinyIoC bootstrapper - registers default route resolver and registers itself as | |
/// INancyModuleCatalog for resolving modules but behaviour can be overridden if required. | |
/// </summary> | |
public class DefaultNancyBootstrapper : NancyBootstrapperBase<TinyIoCContainer>, INancyBootstrapperPerRequestRegistration<TinyIoCContainer>, INancyModuleCatalog | |
{ | |
/// <summary> | |
/// Container instance | |
/// </summary> | |
protected TinyIoCContainer container; | |
/// <summary> | |
/// Resolve INancyEngine | |
/// </summary> | |
/// <returns>INancyEngine implementation</returns> | |
protected sealed override INancyEngine GetEngineInternal() | |
{ | |
return this.container.Resolve<INancyEngine>(); | |
} | |
/// <summary> | |
/// Get the moduleKey generator | |
/// </summary> | |
/// <returns>IModuleKeyGenerator instance</returns> | |
protected sealed override IModuleKeyGenerator GetModuleKeyGenerator() | |
{ | |
return this.container.Resolve<IModuleKeyGenerator>(); | |
} | |
/// <summary> | |
/// Configures the container using AutoRegister followed by registration | |
/// of default INancyModuleCatalog and IRouteResolver. | |
/// </summary> | |
/// <param name="existingContainer"></param> | |
protected override void ConfigureApplicationContainer(TinyIoCContainer existingContainer) | |
{ | |
base.ConfigureApplicationContainer(existingContainer); | |
existingContainer.AutoRegister(); | |
} | |
public virtual void ConfigureRequestContainer(TinyIoCContainer existingContainer) | |
{ | |
} | |
protected override void RegisterViewEngines(TinyIoCContainer container, IEnumerable<Type> viewEngineTypes) | |
{ | |
this.container.Register(typeof(IViewEngine), viewEngineTypes.First()).AsSingleton(); | |
this.container.RegisterMultiple<IViewEngine>(viewEngineTypes).AsSingleton(); | |
var test = container.ResolveAll<IViewEngine>(); | |
var i = 10; | |
} | |
/// <summary> | |
/// Creates a new container instance | |
/// </summary> | |
/// <returns>New container</returns> | |
protected sealed override TinyIoCContainer CreateContainer() | |
{ | |
this.container = new TinyIoCContainer(); | |
return this.container; | |
} | |
/// <summary> | |
/// Registers all modules in the container as multi-instance | |
/// </summary> | |
/// <param name="moduleRegistrations">NancyModule registration types</param> | |
protected sealed override void RegisterModules(IEnumerable<ModuleRegistration> moduleRegistrations) | |
{ | |
foreach (var registrationType in moduleRegistrations) | |
{ | |
this.container.Register(typeof(NancyModule), registrationType.ModuleType, registrationType.ModuleKey).AsMultiInstance(); | |
} | |
} | |
/// <summary> | |
/// Register the default implementations of internally used types into the container as singletons | |
/// </summary> | |
protected sealed override void RegisterDefaults(TinyIoCContainer existingContainer, IEnumerable<TypeRegistration> typeRegistrations) | |
{ | |
existingContainer.Register<INancyModuleCatalog>(this); | |
foreach (var typeRegistration in typeRegistrations) | |
{ | |
existingContainer.Register(typeRegistration.RegistrationType, typeRegistration.ImplementationType).AsSingleton(); | |
} | |
} | |
/// <summary> | |
/// Get all NancyModule implementation instances | |
/// </summary> | |
/// <returns>IEnumerable of NancyModule</returns> | |
public IEnumerable<NancyModule> GetAllModules() | |
{ | |
var childContainer = this.container.GetChildContainer(); | |
this.ConfigureRequestContainer(childContainer); | |
return childContainer.ResolveAll<NancyModule>(false); | |
} | |
/// <summary> | |
/// Gets a specific, per-request, module instance from the key | |
/// </summary> | |
/// <param name="moduleKey">ModuleKey</param> | |
/// <returns>NancyModule instance</returns> | |
public NancyModule GetModuleByKey(string moduleKey) | |
{ | |
var childContainer = this.container.GetChildContainer(); | |
this.ConfigureRequestContainer(childContainer); | |
return childContainer.Resolve<NancyModule>(moduleKey); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Nancy.Bootstrapper | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using Nancy.Diagnostics; | |
using Nancy.Routing; | |
using Nancy.Extensions; | |
using ViewEngines; | |
/// <summary> | |
/// Base class for container based Bootstrappers. | |
/// | |
/// There are two component lifecycles, an application level one which is guaranteed to be generated at least once (on app startup) | |
/// and a request level one which should be guaranteed to be generated per-request. Depending on implementation details the application | |
/// lifecycle components may also be generated per request (without any critical issues), but this isn't ideal. | |
/// | |
/// Doesn't have to be used (only INancyBootstrapper is required), but does provide a nice consistent base if possible. | |
/// | |
/// The methods in the base class are all Application level are called as follows: | |
/// | |
/// CreateContainer() - for creating an empty container | |
/// GetModuleTypes() - getting the module types in the application, default implementation grabs from the appdomain | |
/// RegisterModules() - register the modules into the container | |
/// ConfigureApplicationContainer() - register any application lifecycle dependencies | |
/// GetEngineInternal() - construct the container (if required) and resolve INancyEngine | |
/// | |
/// Request level implementations may use <see cref="INancyBootstrapperPerRequestRegistration{TContainer}"/>, or implement custom | |
/// lifetime logic. It is preferred that users have the ability to register per-request scoped dependencies, and that instances retrieved | |
/// via <see cref="INancyModuleCatalog.GetModuleByKey"/> are per-request scoped. | |
/// </summary> | |
/// <typeparam name="TContainer">Container tyope</typeparam> | |
public abstract class NancyBootstrapperBase<TContainer> : INancyBootstrapper | |
where TContainer : class | |
{ | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultRouteResolver { get { return typeof(DefaultRouteResolver); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultRoutePatternMatcher { get { return typeof (DefaultRoutePatternMatcher); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultTemplateEngineSelector { get { return typeof(DefaultTemplateEngineSelector); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultNancyEngine { get { return typeof(NancyEngine); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultModuleKeyGenerator { get { return typeof(DefaultModuleKeyGenerator); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultRouteCache { get { return typeof(DefaultRouteCache); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultRouteCacheProvider { get { return typeof(DefaultRouteCacheProvider); } } | |
/// <summary> | |
/// Type passed into RegisterDefaults - override this to switch out default implementations | |
/// </summary> | |
protected virtual Type DefaultViewLocator { get { return typeof (AspNetTemplateLocator); } } | |
/// <summary> | |
/// Gets the configured INancyEngine | |
/// </summary> | |
/// <returns>Configured INancyEngine</returns> | |
public INancyEngine GetEngine() | |
{ | |
var container = CreateContainer(); | |
ConfigureApplicationContainer(container); | |
RegisterDefaults(container, BuildDefaults()); | |
RegisterModules(GetModuleTypes(GetModuleKeyGenerator())); | |
RegisterViewEngines(container, GetViewEngineTypes()); | |
return GetEngineInternal(); | |
} | |
private IEnumerable<TypeRegistration> BuildDefaults() | |
{ | |
return new[] | |
{ | |
new TypeRegistration(typeof(IRouteResolver), DefaultRouteResolver), | |
new TypeRegistration(typeof(ITemplateEngineSelector), DefaultTemplateEngineSelector), | |
new TypeRegistration(typeof(INancyEngine), DefaultNancyEngine), | |
new TypeRegistration(typeof(IModuleKeyGenerator), DefaultModuleKeyGenerator), | |
new TypeRegistration(typeof(IRouteCache), DefaultRouteCache), | |
new TypeRegistration(typeof(IRouteCacheProvider), DefaultRouteCacheProvider), | |
new TypeRegistration(typeof(IRoutePatternMatcher), DefaultRoutePatternMatcher), | |
new TypeRegistration(typeof(IViewLocator), DefaultViewLocator), | |
}; | |
} | |
/// <summary> | |
/// Resolve INancyEngine | |
/// </summary> | |
/// <returns>INancyEngine implementation</returns> | |
protected abstract INancyEngine GetEngineInternal(); | |
/// <summary> | |
/// Get the moduleKey generator | |
/// </summary> | |
/// <returns>IModuleKeyGenerator instance</returns> | |
protected abstract IModuleKeyGenerator GetModuleKeyGenerator(); | |
/// <summary> | |
/// Returns available NancyModule types | |
/// </summary> | |
/// <returns>IEnumerable containing all NancyModule Type definitions</returns> | |
protected virtual IEnumerable<ModuleRegistration> GetModuleTypes(IModuleKeyGenerator moduleKeyGenerator) | |
{ | |
var moduleType = typeof(NancyModule); | |
var locatedModuleTypes = | |
from assembly in AppDomain.CurrentDomain.GetAssemblies() | |
where !assembly.ReflectionOnly | |
where !assembly.IsDynamic | |
from type in assembly.SafeGetExportedTypes() | |
where !type.IsAbstract | |
where moduleType.IsAssignableFrom(type) | |
select new ModuleRegistration(type, moduleKeyGenerator.GetKeyForModuleType(type)); | |
return locatedModuleTypes; | |
} | |
protected virtual IEnumerable<Type> GetViewEngineTypes() | |
{ | |
var viewEngineTypes = | |
from assembly in AppDomain.CurrentDomain.GetAssemblies() | |
where !assembly.ReflectionOnly | |
where !assembly.IsDynamic | |
from type in assembly.SafeGetExportedTypes() | |
where !type.IsAbstract | |
where typeof(IViewEngine).IsAssignableFrom(type) | |
select type; | |
return viewEngineTypes; | |
} | |
protected abstract void RegisterViewEngines(TContainer container, IEnumerable<Type> viewEngineTypes); | |
/// <summary> | |
/// Create a default, unconfigured, container | |
/// </summary> | |
/// <returns>Container</returns> | |
protected abstract TContainer CreateContainer(); | |
/// <summary> | |
/// Register the default implementations of internally used types into the container as singletons | |
/// </summary> | |
/// <param name="container">Container</param> | |
/// <param name="typeRegistrations">Type registrations to register</param> | |
protected abstract void RegisterDefaults(TContainer container, IEnumerable<TypeRegistration> typeRegistrations); | |
/// <summary> | |
/// Configure the container (register types) for the application level | |
/// <seealso cref="ConfigureRequestContainer"/> | |
/// </summary> | |
/// <param name="container">Container instance</param> | |
protected virtual void ConfigureApplicationContainer(TContainer container) | |
{ | |
} | |
/// <summary> | |
/// Register the given module types into the container | |
/// </summary> | |
/// <param name="moduleRegistrationTypes">NancyModule types</param> | |
protected abstract void RegisterModules(IEnumerable<ModuleRegistration> moduleRegistrationTypes); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment