如何将IoC容器传递给NancyFX?(OWIN,Unity)

9

我有一个Windows服务,在其中使用OWIN和NancyFX来托管一个网站。在我的服务的许多地方,我使用Unity将依赖项注入到类中,大多数是服务。但是,如果我在任何Nancy模块中使用它们,依赖项会被解析两次,因为Nancy使用自己的IoC容器(TinyIoC)。

幸运的是,Nancy允许覆盖默认的IoC容器生成并使用现有的容器来创建nancy引导程序。但是,如何将现有的IUnityContainer传递给引导程序呢?

基本上,所有我需要启动OWIN的是...

WebApp.Start<MyOwinStarter>(url);

如何将Unity容器传递给Nancy启动程序?

4
注入IoC容器。啊,讽刺啊。 - CSJ
3个回答

11

@ccellar 帮我找到了正确的方向。

我创建了一个名为 UnityHelper 的静态类,并包含以下方法:

private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => {
    var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unityConfiguration");
    return new UnityContainer().LoadConfiguration(section);
});

public static IUnityContainer GetConfiguredContainer() {
    return container.Value;
}

创建了一个自定义的 NancyBootstrapper 类:

public NancyBootstrapper(IUnityContainer container) {
    if(container == null)
        throw new ArgumentNullException("container");
    this._unityContainer = container;
}


protected override IUnityContainer GetApplicationContainer() {
    return _unityContainer;
}

然后我将容器传递给我的Web应用程序启动类中的引导程序:

appBuilder.UseNancy(new NancyOptions {
    EnableClientCertificates    = true,
    Bootstrapper
        = new NancyBootstrapper(UnityHelper.GetConfiguredContainer())
});

好棒!


感谢分享。出于某种原因,我还不了解NancyOptions :) - ccellar

7

免责声明:我不确定这是否是解决此问题的最佳/最干净/最好的方法。但对我来说,它是可行的。

我把我的容器(Castle Windsor)包装成了一个单例,具体如下:

public class Container
{
    // static holder for instance, need to use lambda to construct since constructor private
    private static readonly Lazy<IWindsorContainer> instance = new Lazy<IWindsorContainer>(() =>
    {
        var container = new WindsorContainer();
        container.Install(FromAssembly.This());

        return container;
    });

    // private to prevent direct instantiation.
    private Container()
    {
    }

    // accessor for instance
    public static IWindsorContainer Instance
    {
        get
        {
            return instance.Value;
        }
    }
}

在我的自定义引导程序中,我可以像这样访问已经配置好的容器:

然后在我的自定义启动程序中,我可以像这样访问已经配置好的容器:

protected override Castle.Windsor.IWindsorContainer GetApplicationContainer()
{
  return Container.Instance;
}

非常好的解决方案!我已在下面发布了最终答案。=) - Acrotygma

3
实际上,最简单和正确的方法是从您正在使用的Bootstrapper类型继承一个新的启动程序类 - 在您的情况下是WindsorNancyBootstrapper,并重写GetApplicatioContainer方法并返回您的实例。
您可以在此处阅读更多信息: https://github.com/NancyFx/Nancy.bootstrappers.windsor#customizing

这正是我们在答案中所描述的-不是吗? - ccellar

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