Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按请求自动注册_C#_Nancy_Tinyioc - Fatal编程技术网

C# 按请求自动注册

C# 按请求自动注册,c#,nancy,tinyioc,C#,Nancy,Tinyioc,我们用Nancy(和TinyIoc)实现了一个ASP.NET REST服务,它与一个相当大的遗留应用程序接口。我们希望过渡到完全依赖注入。目前,我们的大多数模块直接实例化控制器,并使用NancyContext context属性获取一个上下文类,该类保存请求信息。大概是这样的: public FooModule(ILegacyService legacyService) { Get["/"] = parameters => new FooController(new Request

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

public FooModule(ILegacyService legacyService) {
    Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}
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();
            }
        }
    }
我们希望将控制器直接注入模块中,并通过super duper happy path()处理所有事情:)

我们的问题都源于这样一个事实,即我们需要来自NancyContext的信息。url、标题等。因此,我们尝试了各种方法来实现依赖注入涅磐

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

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

我们发现可以在
ConfigureRequestContainer
中调用
container.AutoRegister()
,但这导致了严重的延迟,因为注册所需的类型数需要几秒钟

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

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


我创建了一个小测试项目(),在其中我尝试了一些解决方案。

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

public FooModule(ILegacyService legacyService) {
    Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}
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()
插入上下文信息:

protectedoverride void RequestStartup(TinyIoCContainer容器、IPipelines管道、NancyContext上下文)
{
base.RequestStartup(容器、管道、上下文);
var requestUrl=container.Resolve();
Context=Context;
}
}

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

我查看了您的测试解决方案。我的第一个想法是,通过将web(Nancy)代码与应用程序代码(IGreeter等)隔离,您会得到很好的服务。我将构建Nancy模块,负责从web请求(路径、查询字符串参数、标题等)中提取所有相关信息,并将其传递给应用程序代码,最后,获取应用程序代码的结果并将其重新格式化为web格式(标题、负载、状态代码等)。然后,该应用程序可以是web不可知的,不需要参考Nancy,也不需要了解URL标题等。我向您的github示例介绍了一些想法。很荣幸能分享一个关于你问题的完整的小例子。谢谢你的评论和例子。非常感谢。我同意,从内部应用程序代码中删除对Nancy/web代码的依赖将是一件好事,而我的示例是一种快速展示我的困境的方法。但是,即使我们抽象出对NancyContext等的依赖,我们仍然需要贯穿代码的各种服务中的URL/头信息。(续)据我所知,你的例子造成的情况与我在问题中提出的情况大致相同。也就是说,我们需要通过调用链携带web上下文信息。在我的问题示例中是RequestContext,在您的示例中是GreetingCommand。我试图通过压缩模块和实际使用上下文信息的类(GreetingMessageService)之间的层(Greeter)来简化我们的情况。因此,我们需要通过Greeter将GreetingCommand带到GreetingMessageService中。(续)在我们的应用程序中,这个调用链非常大,如果我们发现自己需要上下文信息,我们希望避免使用这种管道代码。这就是依赖注入的用武之地,它应该能够挽救这一天。同时,我已经能够创建一个概念证明,如何能够自动注册AsPerRequestSingleton()的所有类。我将补充这一点作为可能的答案。