dnf*_*dnf 3 c# factory quartz.net async-await simple-injector
我正在配置Quartz库以使用Simple Injector,我有正确注册它的问题.问题是,GetScheduler()是异步这个代码注册Task<IScheduler>不IScheduler
container.Register(async () =>
{
return await container.GetInstance<ISchedulerFactory>().GetScheduler();
});
Run Code Online (Sandbox Code Playgroud)
如何在Simple Injector中注册异步的工厂方法?当然,我可以等使用效果Result的Task,但也许还有其他办法吗?
虽然您可以注册和注入Task<ISceduler>,但Simple Injector不支持异步工厂方法的注册,因为它的GetInstance方法是同步的.
事实上,没有DI Container支持这一点,他们也不应该支持.对象组合应该快速可靠,并且在对象组合期间不应该进行I/O操作.
在对象组合期间运行I/O(以及因此异步)操作会导致操作变得缓慢,不可靠并使测试对象构造变得更加困难(因为在此期间外部I/O资源必须可用).
相反,应该在Object Composition之前或Object Composition之后移动异步操作.在对象组合之前意味着在应用程序启动期间,这意味着一次性启动初始化,而在对象组合之后发生的异步操作由对构造的对象图上的组件的调用触发.
在您的情况下,正确的解决方案取决于几个因素.
如果您的应用程序在您的应用程序中只需要一个IScheduler应用程序,则可以factory.GetScheduler在应用程序启动时调用一次并在容器中注册IScheduleras Singleton.这是关于执行异步启动初始化的相关讨论.
但是,如果IScheduler不能是单例,这意味着您使用的代码IScheduler需要变为异步(它可能已经是异步).这可能意味着您需要注入ISchedulerFactory需要使用的组件IScheduler.这样你就可以等待这个GetScheduler方法了.
另一个常见的选择是在这种情况下创建我们正在使用的抽象的虚拟代理实现IScheduler.然而,这在Quartz的情况下不起作用
IScheduler接口有许多成员,并为此创建虚拟代理是非常麻烦的.IScheduler都是异步的,但是有很多不是异步的,比如IsStarted.因此,创建特定于应用程序的抽象更有意义.这意味着隐藏IScheduler异步特定于应用程序的抽象背后的使用.这种抽象将隐藏使用调度程序的复杂性,并通过使其方法异步,您可以通过实现这种新抽象来懒惰地创建调度程序.此实现将是一个隐藏调度程序复杂性的适配器.