AutoFac - 在应用启动时初始化重量级单例对象

4
我们的配置是,使用AutoFac的MVC5 C#应用程序。
我们有许多单例,如果它们在第一个请求时初始化,会给用户带来不好的体验,因为它们的初始化总共需要大约3-4秒钟。我们正在使用AutoFac进行依赖注入,我想知道是否有任何方法可以确保这些单例(或特定的单例)在App_Start上构建,以便在用户发送第一个请求时不浪费时间?如果没有,解决这个问题的最佳方法是什么?
2个回答

3
这类问题的通用解决方案是在代理实现后隐藏这样的重量级对象。这样,您可以在应用程序启动时直接触发初始化过程,而操作在后台运行而不需要阻塞请求(除非它们在请求期间需要未初始化的数据)。

如果您的代码像这样:

// The abstraction in question
public interface IMyService
{
    ServiceData GetData();
}

// The heavy implementation
public class HeavyInitializationService : IMyServic {
    public HeavyInitializationService() {
        // Load data here
        Thread.Sleep(3000);
    }
    public ServiceData GetData() => ...
}

可以按照以下方式创建代理:
public class LazyMyServiceProxy : IMyService {
    private readonly Lazy<IMyService> lazyService;
    public LazyMyServiceProxy(Lazy<IMyService> lazyService) {
        this.lazyService = lazyService;
    }
    public ServiceData GetData() => this.lazyService.Value.GetData();
}

您可以按如下方式使用此代理:
Lazy<IMyService> lazyService = new Lazy<IMyService>(() =>
    new HeavyInitializationService());

container.Register<IMyService>(c => new LazyMyServiceProxy(lazyService))
    .SingleInstance();

// Trigger the creation of the heavy data on a background thread:
Task.Factory.StartNew(() => {
    // Triggers the creation of HeavyInitializationService on background thread.
    var v = lazyService.Value;
});

3
这可能是解决问题的更好方案,因为它在某种程度上绕过了长时间的应用程序启动时间,否则您可能会遇到,但您也可以使用Autofac的IStartableAutoActivate支持。您可能可以将其与此处的后台初始化策略结合使用。 - Travis Illig

0
根据@Travis Illig的评论所说,只需使用.AutoActivate()
container
    .RegisterType<HeavyInitializationService>()
    .As<IMyService>()
    .SingleInstance()
    .AutoActivate();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接