在 MVVM 应用程序中使用 IoC 容器按请求单例初始化

By-request singleton initialization using IoC container in MVVM application

我的 WPF 应用程序使用 Caliburn.Micro 作为 MVVM 框架,Entity Framework 作为数据访问技术。应用程序的目的是维护数据库。有多个 Views 由菜单和结果数据网格组成。使用菜单控件,用户指定必须在结果数据网格中显示哪些数据库数据。不同 Views 中的一些 ComboBox 绑定到它们 ViewModels 中的相同属性 List<EntityName>。(菜单有相同的项目可供选择)。当 ViewModel 初始化时,每个列表都从数据库加载。我不想为每个视图从数据库加载相同的列表,我想做一次。为了实现这一点,我已经将此 List 属性移动到另一个 class MenuLists 使用 PreloadLists() 方法从数据库中获取列表一次,然后将此 class 作为单例注入到每个 ViewModel 使用 Caliburn 的内置 IoC 容器。像这样:

IoC 容器配置:

container.PerRequest<KitchenOneViewModel>();
container.PerRequest<KitchenTwoViewModel>();
container.Singleton<IMenuLists, MenuLists>();

MenuLists class:

public class MenuLists : IMenuLists
{

    public List<Meat> MeatLst { get; set; }
    public List<Fish> FishLst { get; set; }

    public void PreloadLists()
    {
        using (var db = new DBEntities())
        {
            MeatLst = db.Meat.OrderBy(x => x.MeatName).ToList();
            FishLst = db.Fish.OrderBy(x => x.FishName).ToList();
        }
    }
}

在 ViewModel 中注入:

public KitchenOneViewModel(IMenuLists menuLists)
    {
        _menuLists = menuLists;
    }

问题是我需要以某种方式调用 MenuLists.PreloadLists(),但是如果我在 MenuLists 构造器中这样做,我将首先 UI 冻结 ViewModel 初始化,因为将调用 MenuLists(具有昂贵的 PreloadLists() 数据库访问操作)的构造函数。我不知道 View 中的什么会先打开,所以我不能从那里调用 PreloadLists 方法。我需要预加载我的列表一次而不冻结 UI。我该如何解决?也许以某种方式延迟 MenuLists 初始化?

要么单独延迟加载每个列表以减少初始化时间,例如:

//only initialized when it's used
private static Lazy<List<Meat>> meatList 
     = new Lazy<List<Meat>>(
             () =>
             {
                 //load single list here
             }
     );
public List<Meat> MeatList { get{ return meanList.Value; } }

...或者如果您想立即初始化所有内容,请在应用程序启动时执行,而不是等待 ViewModel 实例化。

或者,如果不需要阻塞,您可以考虑将初始化设为 async