Nancy IoC根据请求自动注册

本文关键字:注册 请求 IoC Nancy | 更新日期: 2023-09-27 18:10:07

我们有一个ASP。NET REST服务由Nancy(和TinyIoc)实现,它与一个相当大的遗留应用程序接口。我们希望过渡到完全依赖注入。目前,我们的大多数模块直接实例化控制器,并采用一个context类,该类使用NancyContext Context属性保存请求信息。像这样:

public FooModule(ILegacyService legacyService) {
    Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}

我们希望直接在模块中注入控制器,并由super-duper-happy-path处理:)

我们的问题都源于我们需要NancyContext的信息。url, header等。因此,我们尝试了各种方法来达到依赖注入的天堂。

尝试注入控制器失败,因为它们在应用范围内实例化,所以任何对RequestContext的依赖都不会有当前上下文信息。即使在ConfigureRequestContainer中注册RequestContext也不会波及到所有依赖项,并且它们将保留对过期RequestContext的引用。

我们已经尝试使用IRequestStartup注入上下文的属性,这似乎是成功的,直到我们遇到并发问题。不同线程中的同时请求将覆盖应用程序作用域RequestContext

我们发现我们可以在ConfigureRequestContainer中调用container.AutoRegister(),但这会导致严重的延迟,因为注册需要几秒钟的时间。

ConfigureApplicationContainer中使用AsPerRequestSingleton()似乎会注册一次,然后每个请求实例化,但似乎没有办法让自动注册遵守这一点。

似乎我们需要手动注册所有类型,并手动保持此配置最新。是这样吗?我们真的希望有某种类型的自动注册每个请求的生命周期。

我创建了一个小的测试项目(https://github.com/Rassi/NancyIocTest),我在其中尝试了一些解决方案。

Nancy IoC根据请求自动注册

使用DefaultNancyAspNetBootstrapper可以创建自己的自动注册,如下所示:

public class Bootstrapper : DefaultNancyAspNetBootstrapper
{
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
        var assemblyClasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsClass);
        foreach (var assemblyClass in assemblyClasses)
        {
            var interfaces = assemblyClass.GetInterfaces();
            if (interfaces.Count() == 1)
            {
                container.Register(interfaces[0], assemblyClass).AsPerRequestSingleton();
            }
        }
    }

然后每个请求实例化所有内容,并且您可以使用RequestStartup():

注入上下文信息:
    protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
    {
        base.RequestStartup(container, pipelines, context);
        var requestUrl = container.Resolve<IRequestUrl>();
        requestUrl.Context = context;
    }
}

这是一个简单的概念证明,它将找到实现一个接口的类,并将其注册到该接口。可能需要处理几个问题,例如:注册实现多个接口的类(可能使用将Name注册到IName的约定)。并处理多个类注册相同的接口