在 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。
我的 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。