在TinyIOC中注册依赖项以在NancyFX中使用

8

我有一个新手问题,关于在TinyIoc中注册额外的依赖项以便在NancyFX中使用。

当运行应用程序时,我仍然遇到以下异常...

Unable to resolve type: AdvancedSearchService.Interfaces.IResponseFactory

Exception Details: TinyIoC.TinyIoCResolutionException: Unable to resolve type: AdvancedSearchService.Interfaces.IResponseFactory

Source Error: 
Line 25:             var container = TinyIoCContainer.Current;
Line 26: 
Line 27:             _responseFactory = container.Resolve<IResponseFactory>();
Line 28:           
Line 29: 

我目前在错误地注册我的依赖项,但我似乎无法找到正确的方法。以下是我的自定义引导程序中的代码。还请注意,我目前没有调用base.ConfigureRequestContainer方法,因为我似乎无法弄清如何将当前上下文传递给它。

protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
    container.Register<IRavenSessionManager>(new RavenSessionManager());
    base.ConfigureApplicationContainer(container);

    ConfigureRequestContainer(container);
}


protected void ConfigureRequestContainer(TinyIoCContainer applicationContainer)
{
    var requestContainer = applicationContainer.GetChildContainer();
    requestContainer.Register<ISearchRepository>(new    SearchRepository(requestContainer.Resolve<IRavenSessionManager>().GetSession()));
    requestContainer.Register<IResponseFactory>(new ResponseFactory(requestContainer.Resolve<ISearchRepository>()));
    //base.ConfigureRequestContainer(requestContainer,[I NEED THE CONTEXT])
}

任何帮助都将不胜感激...显然我的无知没有界限 :)

感谢Steven清理了那个代码..我在发布时甚至没有注意到代码被分开了。 - TheWeekendDeveloper
1个回答

40

好的,不确定从哪里开始...因为您做错了,所以不需要上下文 :-)

首先,您为什么要调用"configure request container",并且为什么要创建子容器?您不需要这样做 :-) 有两个范围,应用程序范围通过覆盖ConfigureApplicationContainer进行配置,请求范围通过覆盖ConfigureRequestContainer进行配置,您不需要自己调用它们,只需根据您想要规定对象的方式覆盖它们。

其次,默认的Nancy启动程序将在ConfigureApplicationContainer的默认实现中“自动注册”所有可以自动注册的内容。在手动注册后调用“base”之后,您实际上是通过自动注册复制了原始注册。要么不调用基类,要么在手动注册之前调用它。而且,不要从ConfigureApplicationContainer中调用ConfigureRequestContainer :-)

如果您不关心所有内容都是应用程序范围(因此单例对象每个请求获取相同的实例),则不需要任何内容,您可以依赖于自动注册。

您当前正在手动构建对象并将其放入容器中,这似乎是一种奇怪的方法。通常,您只需注册类型,让容器在需要时处理实例化。

您没有覆盖ConfigureRequestContainer,您只是创建了一个新方法(具有不同的签名)。

因此,您可能需要的是:

protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
    base.ConfigureApplicationContainer(container);

    // Autoregister will actually do this for us, so we don't need this line,
    // but I'll keep it here to demonstrate. By Default anything registered
    // against an interface will be a singleton instance.
    container.Register<IRavenSessionManager, RavenSessionManager>();
}

// Need to override this, not just make a new method
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
    // Get our session manager - this will "bubble up" to the parent container
    // and get our application scope singleton
    var session = container.Resolve<IRavenSessionManager>().GetSession();

    // We can put this in context.items and it will be disposed when the request ends
    // assuming it implements IDisposable.
    context.Items["RavenSession"] = session;

    // Just guessing what this type is called
    container.Register<IRavenSession>(session);

    container.Register<ISearchRepository, SearchRepository>();
    container.Register<IResponseFactory, ResponseFactory>();
}

4
Nancy也会自动解决模块(和其他类型)中的构造函数依赖关系,因此您永远不应该使用TinyIoCContainer.Current并直接从其中解析。只需将依赖项添加到构造函数中即可!谢谢 - TheCodeJunkie
我必须说...对于一个使用GrumpyDev头像的人,我期望会更好一些 :( 而不是这么多的:). 我知道我的代码可能让你非常困惑,所以感谢您的耐心等待。 - TheWeekendDeveloper
顺便说一句:这解决了问题。你发现了我没有意识到的问题,那就是ConfigureRequestContainer方法的不同签名。我最初尝试像你的解决方案一样覆盖它,但未能意识到我正在使用旧的签名。因为Nancy没有识别旧的签名,所以我绝望地创建了我的私有方法 :)。奇怪的是,最终我将base.ConfigureRequestManager(contianer,context)添加到了我的私有方法中,但未能建立联系。那时我的大脑已经崩溃了:)。 - TheWeekendDeveloper
顺便说一句,我喜欢你添加的注册语法register<IType, ConcreteType>()。一开始我是根据你的文档使用它的,但后来由于绝望和无知而更改了。再次感谢你的帮助,并继续在TinyIoc和NancyFx上做出出色的工作。我真的很喜欢它! - TheWeekendDeveloper
谢谢你的建议,CodeJunkie。我会确保将来不再这样做。 - TheWeekendDeveloper
谢谢你的回答。我在测试引导程序中注册模拟对象时遇到了问题,将它们从“ApplicationStartup”移动到“ConfigureApplicationContainer”解决了这个问题。 - c0bra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接