2017-09-24 48 views
2

我正在配置用于简单注射器的Quartz库,并且在正确注册时遇到问题。问题是,GetScheduler()是异步这个代码注册Task<IScheduler>IScheduler简单注射器中的异步工厂

container.Register(async() => 
{ 
     return await container.GetInstance<ISchedulerFactory>().GetScheduler(); 
}); 

如何注册在简单的喷油器是异步工厂方法?当然,我可以使用ResultTask等待结果,但也许有其他方法?

+0

相关:https://stackoverflow.com/questions/45924027/avoiding-all-di-antipatterns-for-types-requiring-asynchronous-initialization – Steven

回答

4

虽然您可以注册并注入Task<ISceduler>,但简单注入器不支持注册异步工厂方法,因为它的方法是同步的。

事实上,没有DI容器支持这一点,他们也不应该。对象组成应该是fast and reliable,并且在对象组合过程中不应发生I/O操作。

在对象合成期间运行I/O(并因此异步)操作会导致操作变慢,不可靠并使测试对象构造变得更加困难(因为在此期间外部I/O资源必须可用) 。

相反,应该在对象组合之前或对象组合之后移动异步操作。在对象组合意味着在应用程序启动期间意味着一次性启动初始化,而在对象组合后发生的异步操作是通过对构造对象图上的组件进行调用触发的。

你的情况下正确的解决方案取决于几个因素。

如果您的应用程序只在您的应用程序需要一个IScheduler,这可能是正确的在应用程序启动时调用一次factory.GetScheduler和注册IScheduler作为容器SingletonHere's a related discussion关于做异步启动初始化。

但是,如果IScheduler不能是单身人士,这意味着您的代码使用IScheduler需要变得异步(它可能已经是)。这可能意味着您需要将ISchedulerFactory注入需要使用IScheduler的组件中。这样你可以等待GetScheduler方法。

另一个常见选项是创建一个我们正在使用的抽象的Virtual Proxy实现,在这种情况下为IScheduler。然而,这并不在石英的情况下,因为

  1. IScheduler界面有许多成员并为创建虚拟代理是非常繁琐的工作。
  2. 它要求IScheduler的所有成员都是异步的,但也有很多不是异步的,例如IsStarted。创建应用程序特定的抽象因此更有意义。

这意味着隐藏IScheduler在异步特定于应用程序的抽象背后的使用。这种抽象将隐藏使用调度程序的复杂性,并且通过使其方法异步,您可以通过实现这个新的抽象来让一个调度程序可以被懒惰地创建。这个实现将是一个隐藏调度器复杂性的适配器。