c# – Simple Injector中的异步工厂

我正在配置Quartz库以使用Simple Injector,我有正确注册它的问题.问题是GetScheduler()是异步的,这段代码正在注册Task< IScheduler>不是IScheduler

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

如何在Simple Injector中注册异步的工厂方法?当然我可以使用任务结果等待结果,但也许还有其他方法?

最佳答案
虽然您可以注册并注入Task< ISceduler>,但Simple Injector不支持异步工厂方法的注册,因为它的GetInstance方法是同步的.

事实上,没有DI Container支持这一点,他们也不应该支持.对象组合应为fast and reliable,并且在对象组合期间不应执行I / O操作.

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

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

在您的情况下,正确的解决方案取决于几个因素.

如果您的应用程序在您的应用程序中只需要一个IScheduler,则可以在应用程序启动时调用factory.GetScheduler一次,并在容器中将IScheduler注册为Singleton. Here’s a related discussion关于进行异步启动初始化.

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

另一个常见选项是创建我们正在使用的抽象的虚拟代理实现,在本例中为IScheduler.然而,这在Quartz的情况下不起作用

> IScheduler接口有许多成员,为此创建虚拟代理非常麻烦.
>它要求IScheduler的所有成员都是异步的,但是有很多不是异步的,比如IsStarted.因此,创建特定于应用程序的抽象更有意义.

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

转载注明原文:c# – Simple Injector中的异步工厂 - 代码日志