【问题标题】:Instantiation failure and singleton-behaviour interaction [NInject1]实例化失败和单例行为交互 [NInject1]
【发布时间】:2010-04-03 14:13:50
【问题描述】:

我已经设置了一个 NInject(使用 1.5 版)绑定,如下所示:

Bind<ISessionFactory>().ToMethod<ISessionFactory>(ctx => 
{
    try
    {
        // create session factory, might fail because of database issues like wrong connection string
    }
    catch (Exception e)
    {
        throw new DatabaseException(e);
    }
}).Using<SingletonBehavior>();

如您所见,此绑定使用单例行为,但也可能在配置不正确时引发异常,例如与数据库的连接字符串错误。

现在,当会话工厂的创建一开始失败(抛出数据库异常)时,NInject 不会再次尝试创建对象,而是始终返回 null。

我需要 NInject 首先检查 null 并在实例为 null 时重新创建,但当然不是在已经成功构造实例时(保持它为单例)。像这样:

var a = Kernel.Get<ISessionFactory>(); // might fail, a = null
// ... change some database settings
var b = Kernel.Get<ISessionFactory>(); // might not fail anymore, b = ISessionFactory object

我需要编写自定义行为还是缺少其他内容?

【问题讨论】:

    标签: singleton inversion-of-control ninject sessionfactory


    【解决方案1】:

    这没有多大意义。

    首先,单例的意义在于依赖于该项目的所有内容都应该看到完全相同的东西 - 如果您的工厂方法要改变主意,这很难实现。

    另外,如果您说的是 NHibernate ISessionFactory(是吗?),它不会出现可以恢复的这种性质的暂时性故障(或者如果可以,您能解释一下原因吗 - 我是没有专家)。我很欣赏 Session 的创建可能会失败(但您不会将其保留为单例),但这与创建工厂失败的情况完全不同(如果您不能依靠工厂来拥有愚蠢的构造函数,那么您能做什么?靠?)。

    就这方面的 NInject 角度而言,创建方法(无论是 Factory 还是 Provider)与作用域是分开的,所以我怀疑是否会有一种方法可以干净地管理您想要做的事情(即使您可以解决开头的两个问题)。我强烈建议您查看源代码 - 它简短而干净,因此如果有答案,它会立即跳出来。下载时间不会超过一分钟 - 去做吧!

    最后,good article on managing NHibernate sessions(IIRC 没有为会话工厂创建失败做出任何规定)

    现在,要实际回答这个问题,无论它是否是一个坏问题 - 如果在创建工厂时可能会发生故障,并且您无法调整工厂以不这样做(重试多少次看起来你见过创建工厂吗?),答案是你将重试逻辑(用于创建工厂)移动到负责创建会话的提供者或方法中,然后可以以你认为合适的方式重试。

    【讨论】:

    • 我说的是 NHibernate。失败的不是 SessionFactory 本身,它有点复杂(使用 unhaddins)。要创建 sessionfactory,它需要一个 ISessionFactoryProvider,而 ISessionFactoryProvider 又需要一个 IConfigurationProvider,它会创建一个可能会失败的 NHibernate 配置,因为它无法连接到数据库......所以最后,我的 SessionFactory 与配置耦合,至少在使用 unhaddins 时。我不想强制执行严格的单例行为。来源:code.google.com/p/testbat/source/browse/trunk/…
    • 简而言之,这就是所谓的:SessionFactory sf = new Configuration().configure().buildSessionFactory();并且 configure() 部分失败,因此配置错误时不会创建 SessionFactory。但是应用程序应该让用户有机会更改配置并尝试再次创建 SessionFactory。
    • @Maximilian Csuk:我有一个想法是这样的。不过,我会坚持我的回应的一般原则:你需要一些东西来保持稳定。如果您支持/想要/需要重试逻辑,那么您有一个工厂,而不是一个简单的单例。这样做的方法是将Session 绑定到一个方法或提供者,然后可以传递失败。 Ninject 不关心重试逻辑,就像 NHibernate 在这个方向上没有任何默认策略一样。
    • 大多数人会说事情应该很快失败。如果我的网站无法连接到数据库,我现在想知道 - 当我启动网站时 - 如果我无法获得会话工厂,它就不是真的活着。这不仅仅是重试和希望最好的问题。这是个问题。另一种看待这个问题的方法是,您想让站点启动但处于“站点关闭模式” - 即,每次请求都重试初始化,并且 a)如果成功则缓存它或 b)让问题冒泡到 [ELMAH]。
    • 如果你真的很高兴你需要开始管理这个,我建议你看看你的 Ninject/平台集成中的钩子点(你的平台是什么?)。如果那里没有一个明确的答案(例如,根据我的回忆,MVC 支持不会太干净地处理这个问题),那么你有一个值得 Ninject 邮件列表的问题。伊恩和那边的人反应灵敏,早餐吃这种东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2017-08-22
    • 2023-04-09
    • 1970-01-01
    • 2019-05-12
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多