如何执行惰性注入的异步初始化 [英] How to perform async initalization of lazy injection

查看:71
本文介绍了如何执行惰性注入的异步初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们要注入一个创建起来很昂贵的对象(例如,它是从数据库中进行初始化的),因此我们通常会使用某种工厂或 Lazy< T> .但是,如果将这个对象注入到使用异步操作方法的MVC或WebApi控制器中,则我们不想在初始化Lazy对象时在昂贵的I/O操作上阻止这些方法,这违背了使用异步.

Let's say we want to inject an object that is expensive to create (let's say it does initialization from a database), so we would typically use some kind of factory or Lazy<T>. However, if we're injecting this object into an MVC or WebApi controller that is using async action methods, we don't want to block these methods on the expensive I/O operation when the Lazy object is initialized, which defeats the purpose of using async.

当然,我可以创建一个异步的初始化"方法,但它违反了许多原则.

Certainly, I could create an "initlize" method that is async, but that violates a number of principles.

以惰性和异步方式访问和初始化注入的对象的最佳选择是什么?

What's the best option for accessing and initializing the injected object in a lazy and async way?

推荐答案

作为对象图一部分并且由容器自动连线的所有组件都应该非常轻巧地创建,因为

All the components that are part of your object graph and are auto-wired by the container should be very lightweight to create, because injection constructors should be simple. Anything that is either runtime data, or one-time data that is costly to create, should not be injected directly into the constructor of a component that is part of your object graph. Async even exaggerates this, because constructors can never be asynchronous; you can't use await in the body of a constructor.

因此,如果某个组件依赖于一些昂贵的数据来创建数据,则应在构造函数之外延迟加载此数据.这样,对象图的构建变得很快,并且不会阻止您创建控制器.

So if a component depends on some expensive to create data, this data should be loaded lazily, outside of the constructor. This way the building of the object graph becomes fast and the creation of your controllers doesn't get blocked.

因此,就像@ScottChamberlain所说的那样,最好的方法可能是将 Lazy< T> Task< T> 混合以成为 Lazy< Task< T>> .如果将此 Lazy< Task< T>> 注入到昂贵组件"的构造函数中(使该组件本身再次轻量化),则可能会获得最佳结果.这有一些明显的好处:

So as @ScottChamberlain already said, probably the nicest way is to mix Lazy<T> with Task<T> to become Lazy<Task<T>>. You would probably gain the best results if you inject this Lazy<Task<T>> into the constructor of your 'expensive component' (making that component itself lightweight again). This has a few clear benefits:

  • 以前昂贵的对象本身变得简单;它不再负责数据的加载.
  • 对象图变得快速且可验证.
  • 将加载策略从延迟加载更改为后台加载变得很容易,而系统中的任何内容都无需更改.

作为最后一点的一个示例,允许将数据加载到后台的操作很简单,如下所示:

As an example of the last point, allowing the data to be loaded in the background can be simply done as follows:

Task<ExpensiveData> data = Task.Run(LoadExpensiveData);

container.RegisterSingleton<ISomeClass>(
    new SomeClass(new Lazy<Task<ExpensiveData>>(() => data)));

这篇关于如何执行惰性注入的异步初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆