using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Nancy; using Nancy.Bootstrapper; using Nancy.Diagnostics; using TinyIoC; namespace NzbDrone.Api { public abstract class TinyIoCNancyBootstrapper : NancyBootstrapperWithRequestContainerBase<TinyIoCContainer> { /// <summary> /// Resolve INancyEngine /// </summary> /// <returns>INancyEngine implementation</returns> protected override sealed INancyEngine GetEngineInternal() { return this.ApplicationContainer.Resolve<INancyEngine>(); } /// <summary> /// Get the moduleKey generator /// </summary> /// <returns>IModuleKeyGenerator instance</returns> protected override sealed IModuleKeyGenerator GetModuleKeyGenerator() { return this.ApplicationContainer.Resolve<IModuleKeyGenerator>(); } /// <summary> /// Create a default, unconfigured, container /// </summary> /// <returns>Container instance</returns> protected override TinyIoCContainer GetApplicationContainer() { return new TinyIoCContainer(); } /// <summary> /// Register the bootstrapper's implemented types into the container. /// This is necessary so a user can pass in a populated container but not have /// to take the responsibility of registering things like INancyModuleCatalog manually. /// </summary> /// <param name="applicationContainer">Application container to register into</param> protected override sealed void RegisterBootstrapperTypes(TinyIoCContainer applicationContainer) { applicationContainer.Register<INancyModuleCatalog>(this); } /// <summary> /// Register the default implementations of internally used types into the container as singletons /// </summary> /// <param name="container">Container to register into</param> /// <param name="typeRegistrations">Type registrations to register</param> protected override sealed void RegisterTypes(TinyIoCContainer container, IEnumerable<TypeRegistration> typeRegistrations) { foreach (var typeRegistration in typeRegistrations) { container.Register(typeRegistration.RegistrationType, typeRegistration.ImplementationType).AsSingleton(); } } /// <summary> /// Register the various collections into the container as singletons to later be resolved /// by IEnumerable{Type} constructor dependencies. /// </summary> /// <param name="container">Container to register into</param> /// <param name="collectionTypeRegistrationsn">Collection type registrations to register</param> protected override sealed void RegisterCollectionTypes(TinyIoCContainer container, IEnumerable<CollectionTypeRegistration> collectionTypeRegistrationsn) { foreach (var collectionTypeRegistration in collectionTypeRegistrationsn) { container.RegisterMultiple(collectionTypeRegistration.RegistrationType, collectionTypeRegistration.ImplementationTypes.Distinct()); } } /// <summary> /// Register the given module types into the container /// </summary> /// <param name="container">Container to register into</param> /// <param name="moduleRegistrationTypes">NancyModule types</param> protected override sealed void RegisterRequestContainerModules(TinyIoCContainer container, IEnumerable<ModuleRegistration> moduleRegistrationTypes) { foreach (var moduleRegistrationType in moduleRegistrationTypes) { container.Register( typeof(INancyModule), moduleRegistrationType.ModuleType, moduleRegistrationType.ModuleKey). AsSingleton(); } } /// <summary> /// Register the given instances into the container /// </summary> /// <param name="container">Container to register into</param> /// <param name="instanceRegistrations">Instance registration types</param> protected override void RegisterInstances(TinyIoCContainer container, IEnumerable<InstanceRegistration> instanceRegistrations) { foreach (var instanceRegistration in instanceRegistrations) { container.Register( instanceRegistration.RegistrationType, instanceRegistration.Implementation); } } /// <summary> /// Creates a per request child/nested container /// </summary> /// <returns>Request container instance</returns> protected override sealed TinyIoCContainer CreateRequestContainer() { return this.ApplicationContainer.GetChildContainer(); } /// <summary> /// Gets the diagnostics for intialisation /// </summary> /// <returns>IDagnostics implementation</returns> protected override IDiagnostics GetDiagnostics() { return this.ApplicationContainer.Resolve<IDiagnostics>(); } /// <summary> /// Gets all registered startup tasks /// </summary> /// <returns>An <see cref="IEnumerable{T}"/> instance containing <see cref="IApplicationStartup"/> instances. </returns> protected override IEnumerable<IApplicationStartup> GetApplicationStartupTasks() { return this.ApplicationContainer.ResolveAll<IApplicationStartup>(false); } /// <summary> /// Gets all registered application registration tasks /// </summary> /// <returns>An <see cref="IEnumerable{T}"/> instance containing <see cref="IApplicationRegistrations"/> instances.</returns> protected override IEnumerable<IApplicationRegistrations> GetApplicationRegistrationTasks() { return this.ApplicationContainer.ResolveAll<IApplicationRegistrations>(false); } /// <summary> /// Retrieve all module instances from the container /// </summary> /// <param name="container">Container to use</param> /// <returns>Collection of NancyModule instances</returns> protected override sealed IEnumerable<INancyModule> GetAllModules(TinyIoCContainer container) { var nancyModules = container.ResolveAll<INancyModule>(false); return nancyModules; } /// <summary> /// Retreive a specific module instance from the container by its key /// </summary> /// <param name="container">Container to use</param> /// <param name="moduleKey">Module key of the module</param> /// <returns>NancyModule instance</returns> protected override sealed INancyModule GetModuleByKey(TinyIoCContainer container, string moduleKey) { return container.Resolve<INancyModule>(moduleKey); } /// <summary> /// Executes auto registation with the given container. /// </summary> /// <param name="container">Container instance</param> private static void AutoRegister(TinyIoCContainer container, IEnumerable<Func<Assembly, bool>> ignoredAssemblies) { var assembly = typeof(NancyEngine).Assembly; var whitelist = new Type[] { }; container.AutoRegister(AppDomain.CurrentDomain.GetAssemblies().Where(a => !ignoredAssemblies.Any(ia => ia(a))), t => t.Assembly != assembly || whitelist.Any(wt => wt == t)); } } }