我正在构建一个ASP.NET Core REST服务。到目前为止,我有一个(正在运行的)ASP.NET Core(2.2)Web应用程序,我已对其进行了更改以使用Lamar IOC。它工作得很漂亮。
我现在想将Nancy(fx)添加到此应用程序,因为,我真的很希望我的Nancy路由。 (我对南希有些迷恋。)
如何将ASP.NET IOC容器连接到Nancy,以免最终没有Lamar容器和TinyIOC容器。
我已经成功地使用structuremap做到了这一点-相当成功,但这很容易-因为有一个StructureMapNancyBootstrapper。我看过创建LamarNancyBootstrapper的过程-但是在ASP.NET环境中,这似乎很棘手/困难/奇怪?
有人做过这样的事情吗?
顺便说一句。我可以在StartUp.Configure方法中掌握“原始” Lamar IContainer,所以这不是问题。问题似乎只是将其归结于南希。
我设法做到了这一点,而且似乎行得通。不知道这是否朝着正确的方向前进。使用下面的代码-NancySimpleViewEngine尚未正确创建...因此,我仍然必须缺少某些内容。
using System;
using System.Collections.Generic;
using System.Linq;
using global::Lamar;
using Nancy.Bootstrapper;
using Nancy.Diagnostics;
using Nancy.ViewEngines;
using Nancy.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Nancy.Bootstrappers.Lamar
{
/// <summary>
/// Nancy bootstrapper for the StructureMap container.
/// </summary>
public abstract class LamarNancyBootstrapper : NancyBootstrapperWithRequestContainerBase<IContainer>, IDisposable
{
private bool isDisposing = false;
protected readonly IContainer _container;
public LamarNancyBootstrapper(IContainer container)
{
_container = container;
}
/// <summary>
/// Gets the diagnostics for initialisation
/// </summary>
/// <returns>An <see cref="IDiagnostics"/> implementation</returns>
protected override IDiagnostics GetDiagnostics()
{
return this.ApplicationContainer.GetInstance<IDiagnostics>();
}
/// <summary>
/// Gets all registered application startup tasks
/// </summary>
/// <returns>An <see cref="System.Collections.Generic.IEnumerable{T}"/> instance containing <see cref="IApplicationStartup"/> instances. </returns>
protected override IEnumerable<IApplicationStartup> GetApplicationStartupTasks()
{
return this.ApplicationContainer.GetAllInstances<IApplicationStartup>();
}
/// <summary>
/// Gets all registered request startup tasks
/// </summary>
/// <returns>An <see cref="IEnumerable{T}"/> instance containing <see cref="IRequestStartup"/> instances.</returns>
protected override IEnumerable<IRequestStartup> RegisterAndGetRequestStartupTasks(IContainer container, Type[] requestStartupTypes)
{
return requestStartupTypes.Select(container.GetInstance).Cast<IRequestStartup>().ToArray();
}
/// <summary>
/// Gets all registered application registration tasks
/// </summary>
/// <returns>An <see cref="System.Collections.Generic.IEnumerable{T}"/> instance containing <see cref="IRegistrations"/> instances.</returns>
protected override IEnumerable<IRegistrations> GetRegistrationTasks()
{
return this.ApplicationContainer.GetAllInstances<IRegistrations>();
}
/// <summary>
/// Resolve <see cref="INancyEngine"/>
/// </summary>
/// <returns><see cref="INancyEngine"/> implementation</returns>
protected override INancyEngine GetEngineInternal()
{
return this.ApplicationContainer.GetInstance<INancyEngine>();
}
/// <summary>
/// Gets the <see cref="INancyEnvironmentConfigurator"/> used by th.
/// </summary>
/// <returns>An <see cref="INancyEnvironmentConfigurator"/> instance.</returns>
protected override INancyEnvironmentConfigurator GetEnvironmentConfigurator()
{
return this.ApplicationContainer.GetInstance<INancyEnvironmentConfigurator>();
}
/// <summary>
/// Get the <see cref="INancyEnvironment" /> instance.
/// </summary>
/// <returns>An configured <see cref="INancyEnvironment" /> instance.</returns>
/// <remarks>The boostrapper must be initialised (<see cref="INancyBootstrapper.Initialise" />) prior to calling this.</remarks>
public override INancyEnvironment GetEnvironment()
{
return this.ApplicationContainer.GetInstance<INancyEnvironment>();
}
/// <summary>
/// Registers an <see cref="INancyEnvironment"/> instance in the container.
/// </summary>
/// <param name="container">The container to register into.</param>
/// <param name="environment">The <see cref="INancyEnvironment"/> instance to register.</param>
protected override void RegisterNancyEnvironment(IContainer container, INancyEnvironment environment)
{
container.Configure(registry => registry.Add( new ServiceDescriptor(typeof(INancyEnvironment), environment)));
}
/// <summary>
/// Gets the application level container
/// </summary>
/// <returns>Container instance</returns>
protected override IContainer GetApplicationContainer()
{
return _container;
}
/// <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 <see cref="INancyModuleCatalog"/> manually.
/// </summary>
/// <param name="applicationContainer">Application container to register into</param>
protected override void RegisterBootstrapperTypes(IContainer applicationContainer)
{
applicationContainer.Configure(registry =>
{
registry.Add(new ServiceDescriptor(typeof(INancyModuleCatalog), this));
registry.Add(new ServiceDescriptor(typeof(IFileSystemReader), new DefaultFileSystemReader()));
});
}
/// <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 void RegisterTypes(IContainer container, IEnumerable<TypeRegistration> typeRegistrations)
{
container.Configure(registry =>
{
foreach (var typeRegistration in typeRegistrations)
{
ServiceLifetime lifeTime = ServiceLifetime.Transient;
if (typeRegistration.Lifetime == Lifetime.Singleton) lifeTime = ServiceLifetime.Singleton;
else if (typeRegistration.Lifetime == Lifetime.PerRequest) lifeTime = ServiceLifetime.Scoped;
registry.Add(new ServiceDescriptor(typeRegistration.RegistrationType, typeRegistration.ImplementationType, lifeTime));
}
});
}
/// <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 void RegisterCollectionTypes(IContainer container, IEnumerable<CollectionTypeRegistration> collectionTypeRegistrationsn)
{
container.Configure(registry =>
{
foreach (var collectionTypeRegistration in collectionTypeRegistrationsn)
{
foreach (var implementationType in collectionTypeRegistration.ImplementationTypes)
{
registry.Add(new ServiceDescriptor(collectionTypeRegistration.RegistrationType, implementationType, ServiceLifetime.Transient));
}
}
});
}
/// <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(IContainer container, IEnumerable<InstanceRegistration> instanceRegistrations)
{
container.Configure(registry =>
{
foreach (var instanceRegistration in instanceRegistrations)
{
registry.Add(new ServiceDescriptor(instanceRegistration.RegistrationType, instanceRegistration.Implementation));
}
});
}
/// <summary>
/// Register the given module types into the request container
/// </summary>
/// <param name="container">Container to register into</param>
/// <param name="moduleRegistrationTypes"><see cref="INancyModule"/> types</param>
protected override void RegisterRequestContainerModules(IContainer container, IEnumerable<ModuleRegistration> moduleRegistrationTypes)
{
container.Configure(registry =>
{
foreach (var registrationType in moduleRegistrationTypes)
{
registry.Add(new ServiceDescriptor(typeof(INancyModule), registrationType.ModuleType, ServiceLifetime.Transient));
}
});
}
/// <summary>
/// Retrieve all module instances from the container
/// </summary>
/// <param name="container">Container to use</param>
/// <returns>Collection of <see cref="INancyModule"/> instances</returns>
protected override IEnumerable<INancyModule> GetAllModules(IContainer container)
{
return container.GetAllInstances<INancyModule>();
}
/// <summary>
/// Retreive a specific module instance from the container
/// </summary>
/// <param name="container">Container to use</param>
/// <param name="moduleType">Type of the module</param>
/// <returns>A <see cref="INancyModule"/> instance</returns>
protected override INancyModule GetModule(IContainer container, Type moduleType)
{
return (INancyModule)container.GetInstance(moduleType);
}
public new void Dispose()
{
if (this.isDisposing)
{
return;
}
this.isDisposing = true;
base.Dispose();
}
}
}